zen_engine/nodes/
variable_json.rs1use 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}