hcl_edit/expr/traversal.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
use crate::expr::Expression;
use crate::{Decor, Decorate, Decorated, Ident};
use std::fmt;
use std::ops::Range;
/// Traverse an expression to access attributes, object keys or element indices.
#[derive(Debug, Clone, Eq)]
pub struct Traversal {
    /// The expression that the access operator is applied to.
    pub expr: Expression,
    /// The traversal operators to apply to `expr` one of the other.
    pub operators: Vec<Decorated<TraversalOperator>>,
    decor: Decor,
    span: Option<Range<usize>>,
}
impl Traversal {
    /// Creates a new `Traversal` structure from an expression and traversal operators that should
    /// be applied to it.
    pub fn new(
        expr: impl Into<Expression>,
        operators: Vec<Decorated<TraversalOperator>>,
    ) -> Traversal {
        Traversal {
            expr: expr.into(),
            operators,
            decor: Decor::default(),
            span: None,
        }
    }
    pub(crate) fn despan(&mut self, input: &str) {
        self.decor.despan(input);
        self.expr.despan(input);
        for operator in &mut self.operators {
            operator.despan(input);
        }
    }
}
impl PartialEq for Traversal {
    fn eq(&self, other: &Self) -> bool {
        self.expr == other.expr && self.operators == other.operators
    }
}
/// The expression traversal operators that are supported by HCL.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TraversalOperator {
    /// The attribute-only splat operator supports only attribute lookups into the elements from a
    /// list, but supports an arbitrary number of them.
    AttrSplat(Decorated<Splat>),
    /// The full splat operator additionally supports indexing into the elements from a list, and
    /// allows any combination of attribute access and index operations.
    FullSplat(Decorated<Splat>),
    /// The attribute access operator returns the value of a single attribute in an object value.
    GetAttr(Decorated<Ident>),
    /// The index operator returns the value of a single element of a collection value based on
    /// the result of the expression.
    Index(Expression),
    /// The legacy index operator returns the value of a single element of a collection value.
    /// Exists only for compatibility with the precursor language HIL. Use the `Index` variant
    /// instead.
    LegacyIndex(Decorated<u64>),
}
impl TraversalOperator {
    pub(crate) fn despan(&mut self, input: &str) {
        match self {
            TraversalOperator::AttrSplat(splat) | TraversalOperator::FullSplat(splat) => {
                splat.decor_mut().despan(input);
            }
            TraversalOperator::GetAttr(ident) => ident.decor_mut().despan(input),
            TraversalOperator::Index(expr) => expr.despan(input),
            TraversalOperator::LegacyIndex(index) => index.decor_mut().despan(input),
        }
    }
}
/// Represents the splat operator (`*`) that is used within a
/// [`AttrSplat`](TraversalOperator::AttrSplat) or [`FullSplat`](TraversalOperator::FullSplat).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Splat;
impl fmt::Display for Splat {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "*")
    }
}
decorate_impl!(Traversal);
span_impl!(Traversal);
forward_decorate_impl!(TraversalOperator => { AttrSplat, FullSplat, GetAttr, Index, LegacyIndex });
forward_span_impl!(TraversalOperator => { AttrSplat, FullSplat, GetAttr, Index, LegacyIndex });