cco 0.2.0

cascading configuration
Documentation
use super::{Expr, ExprEvaluator};
use crate::err::*;
use crate::eval::*;

#[derive(Debug, Clone)]
pub struct TraversalExpr {
    pub object: Index,
    pub key: TraversalKey,
}

impl Expr for TraversalExpr {
    fn resolve(
        &self,
        _index: Index,
        evaluation: &mut dyn ExprEvaluator,
    ) -> Result<ValueOrReference, ErrorKind> {
        let indexer = match &self.key {
            TraversalKey::String(s) => Indexer::String(s.clone()),
            TraversalKey::Number(n) => Indexer::Number(*n),
            &TraversalKey::Expression(index) => evaluation
                .get_value(index)?
                .try_into()
                .map_err(|_| ErrorKind::ExpressionNotAnIndexer { index })?,
        };

        let Some(reference) = evaluation.traverse(self.object, &indexer)? else {
            return Err(ErrorKind::FieldNotFound {
                item: self.object,
                name: indexer.to_string(),
            });
        };

        Ok(reference)
    }

    fn traverse(
        &self,
        _evaluation: &dyn ExprEvaluator,
        expression: Index,
        _name: &Indexer,
    ) -> Result<Option<ValueOrReference>, ErrorKind> {
        Err(ErrorKind::DependenciesNotSatisfied {
            indices: vec![expression],
        })
    }
}