Skip to main content

zen_engine/nodes/
variable_json.rs

1use std::borrow::Cow;
2use std::cell::Ref;
3
4use jsonschema::json::{Array, Json, JsonNumber, Node, NodeIdentity, Object};
5use jsonschema::JsonType;
6use rust_decimal::prelude::ToPrimitive;
7use rust_decimal::Decimal;
8use self_cell::self_cell;
9use serde_json::Value;
10use typed_arena::Arena;
11use zen_types::variable::{MapIter, RcCell, Variable, VariableMap};
12
13pub struct VariableJson;
14
15type MapRef<'a> = Ref<'a, VariableMap>;
16type VecRef<'a> = Ref<'a, Vec<Variable>>;
17
18self_cell!(
19    struct MapGuard {
20        owner: RcCell<VariableMap>,
21
22        #[covariant]
23        dependent: MapRef,
24    }
25);
26
27self_cell!(
28    struct VecGuard {
29        owner: RcCell<Vec<Variable>>,
30
31        #[covariant]
32        dependent: VecRef,
33    }
34);
35
36pub struct Guards {
37    objects: Arena<MapGuard>,
38    arrays: Arena<VecGuard>,
39}
40
41impl Default for Guards {
42    fn default() -> Self {
43        Self {
44            objects: Arena::new(),
45            arrays: Arena::new(),
46        }
47    }
48}
49
50#[derive(Clone, Copy)]
51pub struct VariableNode<'a> {
52    var: &'a Variable,
53    guards: &'a Guards,
54}
55
56impl<'a> VariableNode<'a> {
57    pub fn new(var: &'a Variable, guards: &'a Guards) -> Self {
58        Self { var, guards }
59    }
60}
61
62impl Json for VariableJson {
63    type Node<'a> = VariableNode<'a>;
64    type PreparedKey = Box<str>;
65    type StringBuffer = Variable;
66
67    fn prepare_key(key: &str) -> Box<str> {
68        Box::from(key)
69    }
70
71    fn with_string_node<T>(
72        buffer: &mut Variable,
73        string: &str,
74        f: impl FnOnce(VariableNode<'_>) -> T,
75    ) -> T {
76        *buffer = Variable::String((string).into());
77        let guards = Guards::default();
78        f(VariableNode::new(buffer, &guards))
79    }
80}
81
82pub struct VariableNumber(Decimal);
83
84impl JsonNumber for VariableNumber {
85    fn as_u64(&self) -> Option<u64> {
86        self.0.is_integer().then(|| self.0.to_u64()).flatten()
87    }
88
89    fn as_i64(&self) -> Option<i64> {
90        self.0.is_integer().then(|| self.0.to_i64()).flatten()
91    }
92
93    fn as_f64(&self) -> Option<f64> {
94        self.0.to_f64()
95    }
96
97    fn as_str(&self) -> Cow<'_, str> {
98        Cow::Owned(self.0.normalize().to_string())
99    }
100
101    fn to_number(&self) -> Cow<'_, serde_json::Number> {
102        let normalized = self.0.normalize().to_string();
103        #[cfg(feature = "arbitrary_precision")]
104        let number = serde_json::Number::from_string_unchecked(normalized);
105        #[cfg(not(feature = "arbitrary_precision"))]
106        let number = normalized
107            .parse()
108            .ok()
109            .or_else(|| self.0.to_f64().and_then(serde_json::Number::from_f64))
110            .unwrap_or_else(|| serde_json::Number::from(0));
111        Cow::Owned(number)
112    }
113}
114
115impl<'a> Node<'a, VariableJson> for VariableNode<'a> {
116    type Object = ObjectNode<'a>;
117    type Array = ArrayNode<'a>;
118    type Number = VariableNumber;
119
120    fn as_object(&self) -> Option<ObjectNode<'a>> {
121        let Variable::Object(cell) = self.var else {
122            return None;
123        };
124
125        let guard = self
126            .guards
127            .objects
128            .alloc(MapGuard::new(cell.clone(), |cell| cell.borrow()));
129        Some(ObjectNode {
130            map: guard.borrow_dependent(),
131            guards: self.guards,
132        })
133    }
134
135    fn as_array(&self) -> Option<ArrayNode<'a>> {
136        let Variable::Array(cell) = self.var else {
137            return None;
138        };
139
140        let guard = self
141            .guards
142            .arrays
143            .alloc(VecGuard::new(cell.clone(), |cell| cell.borrow()));
144        Some(ArrayNode {
145            items: guard.borrow_dependent().as_slice(),
146            guards: self.guards,
147        })
148    }
149
150    fn as_string(&self) -> Option<Cow<'a, str>> {
151        match self.var {
152            Variable::String(string) => Some(Cow::Borrowed(string.as_str())),
153            Variable::Dynamic(dynamic) => Some(Cow::Owned(dynamic.to_string())),
154            _ => None,
155        }
156    }
157
158    fn as_number(&self) -> Option<VariableNumber> {
159        match self.var {
160            Variable::Number(number) => Some(VariableNumber(*number)),
161            _ => None,
162        }
163    }
164
165    fn as_boolean(&self) -> Option<bool> {
166        match self.var {
167            Variable::Bool(boolean) => Some(*boolean),
168            _ => None,
169        }
170    }
171
172    fn is_null(&self) -> bool {
173        matches!(self.var, Variable::Null)
174    }
175
176    fn json_type(&self) -> JsonType {
177        match self.var {
178            Variable::Null => JsonType::Null,
179            Variable::Bool(_) => JsonType::Boolean,
180            Variable::Number(_) => JsonType::Number,
181            Variable::String(_) => JsonType::String,
182            Variable::Array(_) => JsonType::Array,
183            Variable::Object(_) => JsonType::Object,
184            Variable::Dynamic(_) => JsonType::String,
185        }
186    }
187
188    fn to_value(&self) -> Cow<'a, Value> {
189        Cow::Owned(Variable::to_value(self.var))
190    }
191
192    fn identity(&self) -> Option<NodeIdentity> {
193        Some(NodeIdentity::new(
194            std::ptr::from_ref::<Variable>(self.var) as usize
195        ))
196    }
197}
198
199pub struct ObjectNode<'a> {
200    map: &'a VariableMap,
201    guards: &'a Guards,
202}
203
204impl<'a> Object<'a, VariableJson> for ObjectNode<'a> {
205    type Node = VariableNode<'a>;
206    type MemberName = &'a str;
207    type MembersIter = VariableMembersIter<'a>;
208
209    fn len(&self) -> usize {
210        self.map.len()
211    }
212
213    fn get(&self, key: &Box<str>) -> Option<VariableNode<'a>> {
214        self.map
215            .get_str(key)
216            .map(|var| VariableNode::new(var, self.guards))
217    }
218
219    fn members(&self) -> VariableMembersIter<'a> {
220        VariableMembersIter {
221            iter: self.map.iter(),
222            guards: self.guards,
223        }
224    }
225}
226
227pub struct VariableMembersIter<'a> {
228    iter: MapIter<'a>,
229    guards: &'a Guards,
230}
231
232impl<'a> Iterator for VariableMembersIter<'a> {
233    type Item = (&'a str, VariableNode<'a>);
234
235    fn next(&mut self) -> Option<Self::Item> {
236        self.iter
237            .next()
238            .map(|(name, value)| (name.as_str(), VariableNode::new(value, self.guards)))
239    }
240}
241
242pub struct ArrayNode<'a> {
243    items: &'a [Variable],
244    guards: &'a Guards,
245}
246
247impl<'a> Array<'a, VariableJson> for ArrayNode<'a> {
248    type Node = VariableNode<'a>;
249    type ElementsIter = VariableElementsIter<'a>;
250
251    fn len(&self) -> usize {
252        self.items.len()
253    }
254
255    fn elements(&self) -> VariableElementsIter<'a> {
256        VariableElementsIter {
257            iter: self.items.iter(),
258            guards: self.guards,
259        }
260    }
261}
262
263pub struct VariableElementsIter<'a> {
264    iter: std::slice::Iter<'a, Variable>,
265    guards: &'a Guards,
266}
267
268impl<'a> Iterator for VariableElementsIter<'a> {
269    type Item = VariableNode<'a>;
270
271    fn next(&mut self) -> Option<Self::Item> {
272        self.iter
273            .next()
274            .map(|var| VariableNode::new(var, self.guards))
275    }
276}