hcl/expr/
variable.rs

1use crate::{Identifier, InternalString, Result};
2use serde::Deserialize;
3use std::ops::Deref;
4
5/// A type representing a variable in an HCL expression.
6///
7/// It is a wrapper around the [`Identifier`] type and behaves the same in most cases via its
8/// `Deref` implementation.
9///
10/// This is a separate type to differentiate between bare identifiers and variable identifiers
11/// which have different semantics in different scopes.
12#[derive(Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
13#[serde(transparent)]
14pub struct Variable(Identifier);
15
16impl Variable {
17    /// Create a new `Variable` after validating that it only contains characters that are allowed
18    /// in HCL identifiers.
19    ///
20    /// See the documentation of [`Identifier::new`] for more.
21    ///
22    /// # Errors
23    ///
24    /// If `ident` contains characters that are not allowed in HCL identifiers or if it is empty an
25    /// error will be returned.
26    pub fn new<T>(ident: T) -> Result<Self>
27    where
28        T: Into<InternalString>,
29    {
30        Identifier::new(ident).map(Variable)
31    }
32
33    /// Create a new `Variable` after sanitizing the input if necessary.
34    ///
35    /// See the documentation of [`Identifier::sanitized`] for more.
36    pub fn sanitized<T>(ident: T) -> Self
37    where
38        T: AsRef<str>,
39    {
40        Variable(Identifier::sanitized(ident))
41    }
42
43    /// Create a new `Variable` from an identifier without checking if it is valid in HCL.
44    ///
45    /// It is the caller's responsibility to ensure that the variable identifier is valid.
46    ///
47    /// See the documentation of [`Identifier::unchecked`] for more.
48    ///
49    /// # Safety
50    ///
51    /// This function is not marked as unsafe because it does not cause undefined behaviour.
52    /// However, attempting to serialize an invalid variable identifier to HCL will produce invalid
53    /// output.
54    pub fn unchecked<T>(ident: T) -> Self
55    where
56        T: Into<InternalString>,
57    {
58        Variable(Identifier::unchecked(ident))
59    }
60
61    /// Consume `self` and return the wrapped `Identifier`.
62    pub fn into_inner(self) -> Identifier {
63        self.0
64    }
65}
66
67impl Deref for Variable {
68    type Target = Identifier;
69
70    fn deref(&self) -> &Self::Target {
71        &self.0
72    }
73}
74
75impl From<Identifier> for Variable {
76    fn from(ident: Identifier) -> Self {
77        Variable(ident)
78    }
79}