hcl_edit/structure/
attribute.rs

1use crate::expr::Expression;
2use crate::{Decor, Decorate, Decorated, Ident, Span};
3use std::ops::{self, Range};
4
5/// Represents an HCL attribute which consists of an attribute key and a value expression.
6///
7/// In HCL syntax this is represented as:
8///
9/// ```hcl
10/// key = value
11/// ```
12///
13/// Use [`Attribute::new`] to construct an [`Attribute`] from a value that is convertible to this
14/// crate's [`Expression`] type.
15#[derive(Debug, Clone, Eq)]
16pub struct Attribute {
17    /// The HCL attribute's key.
18    pub key: Decorated<Ident>,
19    /// The value expression of the HCL attribute.
20    pub value: Expression,
21
22    decor: Decor,
23    span: Option<Range<usize>>,
24}
25
26impl Attribute {
27    /// Creates a new `Attribute` from a key and a value.
28    pub fn new(key: impl Into<Decorated<Ident>>, value: impl Into<Expression>) -> Attribute {
29        Attribute {
30            key: key.into(),
31            value: value.into(),
32            decor: Decor::default(),
33            span: None,
34        }
35    }
36
37    /// Returns `true` if the attribute has the given key.
38    ///
39    /// # Example
40    ///
41    /// ```
42    /// use hcl_edit::{structure::Attribute, Ident};
43    ///
44    /// let attr = Attribute::new(Ident::new("foo"), "bar");
45    /// assert!(attr.has_key("foo"));
46    /// assert!(!attr.has_key("bar"));
47    /// ```
48    #[inline]
49    pub fn has_key(&self, key: &str) -> bool {
50        self.key.as_str() == key
51    }
52
53    pub(crate) fn despan(&mut self, input: &str) {
54        self.decor.despan(input);
55        self.key.decor_mut().despan(input);
56        self.value.despan(input);
57    }
58}
59
60impl PartialEq for Attribute {
61    fn eq(&self, other: &Self) -> bool {
62        self.key == other.key && self.value == other.value
63    }
64}
65
66decorate_impl!(Attribute);
67span_impl!(Attribute);
68
69/// Allows mutable access to the value and surrounding [`Decor`] of an [`Attribute`] but not to its
70/// key.
71///
72/// This type wraps the attribute returned by
73/// [`Body::get_attribute_mut`](crate::structure::Body::get_attribute_mut) and in the iterator
74/// returned by [`Body::attributes_mut`](crate::structure::Body::attributes_mut).
75pub struct AttributeMut<'a> {
76    attr: &'a mut Attribute,
77}
78
79impl<'a> AttributeMut<'a> {
80    pub(crate) fn new(attr: &'a mut Attribute) -> AttributeMut<'a> {
81        AttributeMut { attr }
82    }
83
84    /// Returns an immutable reference to the wrapped `Attribute`.
85    pub fn get(&self) -> &Attribute {
86        self.attr
87    }
88
89    /// Returns a mutable reference to the wrapped `Attribute`'s key's decor.
90    pub fn key_decor_mut(&mut self) -> &mut Decor {
91        self.attr.key.decor_mut()
92    }
93
94    /// Returns a mutable reference to the wrapped `Attribute`'s value.
95    pub fn value_mut(&mut self) -> &mut Expression {
96        &mut self.attr.value
97    }
98}
99
100impl<'a> ops::Deref for AttributeMut<'a> {
101    type Target = Attribute;
102
103    #[inline]
104    fn deref(&self) -> &Self::Target {
105        self.get()
106    }
107}
108
109impl<'a> Decorate for AttributeMut<'a> {
110    fn decor(&self) -> &Decor {
111        self.attr.decor()
112    }
113
114    fn decor_mut(&mut self) -> &mut Decor {
115        self.attr.decor_mut()
116    }
117}
118
119impl<'a> Span for AttributeMut<'a> {
120    fn span(&self) -> Option<Range<usize>> {
121        self.attr.span()
122    }
123}