hcl_edit/structure/
attribute.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::expr::Expression;
use crate::{Decor, Decorate, Decorated, Ident, Span};
use std::ops::{self, Range};

/// Represents an HCL attribute which consists of an attribute key and a value expression.
///
/// In HCL syntax this is represented as:
///
/// ```hcl
/// key = value
/// ```
///
/// Use [`Attribute::new`] to construct an [`Attribute`] from a value that is convertible to this
/// crate's [`Expression`] type.
#[derive(Debug, Clone, Eq)]
pub struct Attribute {
    /// The HCL attribute's key.
    pub key: Decorated<Ident>,
    /// The value expression of the HCL attribute.
    pub value: Expression,

    decor: Decor,
    span: Option<Range<usize>>,
}

impl Attribute {
    /// Creates a new `Attribute` from a key and a value.
    pub fn new(key: impl Into<Decorated<Ident>>, value: impl Into<Expression>) -> Attribute {
        Attribute {
            key: key.into(),
            value: value.into(),
            decor: Decor::default(),
            span: None,
        }
    }

    /// Returns `true` if the attribute has the given key.
    ///
    /// # Example
    ///
    /// ```
    /// use hcl_edit::{structure::Attribute, Ident};
    ///
    /// let attr = Attribute::new(Ident::new("foo"), "bar");
    /// assert!(attr.has_key("foo"));
    /// assert!(!attr.has_key("bar"));
    /// ```
    #[inline]
    pub fn has_key(&self, key: &str) -> bool {
        self.key.as_str() == key
    }

    pub(crate) fn despan(&mut self, input: &str) {
        self.decor.despan(input);
        self.key.decor_mut().despan(input);
        self.value.despan(input);
    }
}

impl PartialEq for Attribute {
    fn eq(&self, other: &Self) -> bool {
        self.key == other.key && self.value == other.value
    }
}

decorate_impl!(Attribute);
span_impl!(Attribute);

/// Allows mutable access to the value and surrounding [`Decor`] of an [`Attribute`] but not to its
/// key.
///
/// This type wraps the attribute returned by
/// [`Body::get_attribute_mut`](crate::structure::Body::get_attribute_mut) and in the iterator
/// returned by [`Body::attributes_mut`](crate::structure::Body::attributes_mut).
pub struct AttributeMut<'a> {
    attr: &'a mut Attribute,
}

impl<'a> AttributeMut<'a> {
    pub(crate) fn new(attr: &'a mut Attribute) -> AttributeMut<'a> {
        AttributeMut { attr }
    }

    /// Returns an immutable reference to the wrapped `Attribute`.
    pub fn get(&self) -> &Attribute {
        self.attr
    }

    /// Returns a mutable reference to the wrapped `Attribute`'s key's decor.
    pub fn key_decor_mut(&mut self) -> &mut Decor {
        self.attr.key.decor_mut()
    }

    /// Returns a mutable reference to the wrapped `Attribute`'s value.
    pub fn value_mut(&mut self) -> &mut Expression {
        &mut self.attr.value
    }
}

impl<'a> ops::Deref for AttributeMut<'a> {
    type Target = Attribute;

    #[inline]
    fn deref(&self) -> &Self::Target {
        self.get()
    }
}

impl<'a> Decorate for AttributeMut<'a> {
    fn decor(&self) -> &Decor {
        self.attr.decor()
    }

    fn decor_mut(&mut self) -> &mut Decor {
        self.attr.decor_mut()
    }
}

impl<'a> Span for AttributeMut<'a> {
    fn span(&self) -> Option<Range<usize>> {
        self.attr.span()
    }
}