vrl/compiler/expression/
object.rs

1use std::{collections::BTreeMap, fmt, ops::Deref};
2
3use crate::value::{KeyString, Value};
4use crate::{
5    compiler::{
6        Context, Expression, TypeDef,
7        expression::{Expr, Resolved},
8        state::{TypeInfo, TypeState},
9    },
10    value::Kind,
11};
12
13#[derive(Debug, Clone, PartialEq)]
14pub struct Object {
15    inner: BTreeMap<KeyString, Expr>,
16}
17
18impl Object {
19    #[must_use]
20    pub fn new(inner: BTreeMap<KeyString, Expr>) -> Self {
21        Self { inner }
22    }
23}
24
25impl Deref for Object {
26    type Target = BTreeMap<KeyString, Expr>;
27
28    fn deref(&self) -> &Self::Target {
29        &self.inner
30    }
31}
32
33impl Expression for Object {
34    fn resolve(&self, ctx: &mut Context) -> Resolved {
35        self.inner
36            .iter()
37            .map(|(key, expr)| expr.resolve(ctx).map(|v| (key.clone(), v)))
38            .collect::<Result<BTreeMap<_, _>, _>>()
39            .map(Value::Object)
40    }
41
42    fn resolve_constant(&self, state: &TypeState) -> Option<Value> {
43        self.inner
44            .iter()
45            .map(|(key, expr)| expr.resolve_constant(state).map(|v| (key.clone(), v)))
46            .collect::<Option<BTreeMap<_, _>>>()
47            .map(Value::Object)
48    }
49
50    fn type_info(&self, state: &TypeState) -> TypeInfo {
51        let mut state = state.clone();
52        let mut fallible = false;
53        let mut returns = Kind::never();
54
55        let mut type_defs = BTreeMap::new();
56        for (k, expr) in &self.inner {
57            let type_def = expr.apply_type_info(&mut state).upgrade_undefined();
58            returns.merge_keep(type_def.returns().clone(), false);
59
60            // If any expression is fallible, the entire object is fallible.
61            fallible |= type_def.is_fallible();
62
63            // If any expression aborts, the entire object aborts
64            if type_def.is_never() {
65                return TypeInfo::new(
66                    state,
67                    TypeDef::never()
68                        .maybe_fallible(fallible)
69                        .with_returns(returns),
70                );
71            }
72            type_defs.insert(k.clone(), type_def);
73        }
74
75        let collection = type_defs
76            .into_iter()
77            .map(|(field, type_def)| (field.into(), type_def.into()))
78            .collect::<BTreeMap<_, _>>();
79
80        let result = TypeDef::object(collection)
81            .maybe_fallible(fallible)
82            .with_returns(returns);
83        TypeInfo::new(state, result)
84    }
85}
86
87impl fmt::Display for Object {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        let exprs = self
90            .inner
91            .iter()
92            .map(|(k, v)| format!(r#""{k}": {v}"#))
93            .collect::<Vec<_>>()
94            .join(", ");
95
96        write!(f, "{{ {exprs} }}")
97    }
98}
99
100impl From<BTreeMap<KeyString, Expr>> for Object {
101    fn from(inner: BTreeMap<KeyString, Expr>) -> Self {
102        Self { inner }
103    }
104}