1use crate::symbol::Symbol;
2use crate::variable::map::Entry;
3use crate::variable::ref_ser::RefSerializer;
4use rust_decimal::Decimal;
5use rust_decimal::prelude::Zero;
6use serde_json::Value;
7use std::any::Any;
8use std::cell::RefCell;
9use std::fmt::{Debug, Display, Formatter};
10use std::ops::Deref;
11use std::rc::Rc;
12
13use crate::rcvalue::RcValue;
14pub use crate::variable::conv::VariableConversionError;
15pub use crate::variable::ref_deser::RefDeserializeError;
16use crate::variable::ref_deser::RefDeserializer;
17pub use de::VariableDeserializer;
18pub use impls::ToVariable;
19
20mod conv;
21mod de;
22mod impls;
23mod map;
24mod ref_deser;
25mod ref_ser;
26mod ser;
27
28pub use crate::rccell::RcCell;
29
30pub use crate::variable::map::{Iter as MapIter, VariableMap};
31
32thread_local! {
33 static DOLLAR_KEY_RC: Rc<str> = Rc::from("$");
34 static ROOT_KEY_RC: Rc<str> = Rc::from("$root");
35}
36
37pub enum Variable {
38 Null,
39 Bool(bool),
40 Number(Decimal),
41 String(Symbol),
42 Array(RcCell<Vec<Variable>>),
43 Object(RcCell<VariableMap>),
44 Dynamic(Rc<dyn DynamicVariable>),
45}
46
47pub trait DynamicVariable: Display {
48 fn type_name(&self) -> &'static str;
49
50 fn as_any(&self) -> &dyn Any;
51
52 fn to_value(&self) -> Value;
53}
54
55impl Variable {
56 pub fn dollar_key() -> Symbol {
57 Symbol::from_static("$")
58 }
59
60 pub fn root_key() -> Symbol {
61 Symbol::from_static("$root")
62 }
63
64 pub fn nodes_key() -> Symbol {
65 Symbol::from_static("$nodes")
66 }
67
68 pub fn key(name: &str) -> Symbol {
69 Symbol::from(name)
70 }
71
72 pub fn dollar_key_rc() -> Rc<str> {
73 DOLLAR_KEY_RC.with(Rc::clone)
74 }
75
76 pub fn root_key_rc() -> Rc<str> {
77 ROOT_KEY_RC.with(Rc::clone)
78 }
79
80 pub fn from_array(arr: Vec<Self>) -> Self {
81 Self::Array(Rc::new(RefCell::new(arr)))
82 }
83
84 pub fn serialize_ref(&self) -> RcValue {
85 RefSerializer::new().serialize(self)
86 }
87
88 pub fn deserialize_ref(serialized: RcValue) -> Result<Self, RefDeserializeError> {
89 RefDeserializer::new().deserialize(serialized)
90 }
91
92 pub fn from_object(obj: VariableMap) -> Self {
93 Self::Object(Rc::new(RefCell::new(obj)))
94 }
95
96 pub fn empty_object() -> Self {
97 Variable::Object(Default::default())
98 }
99
100 pub fn empty_array() -> Self {
101 Variable::Array(Default::default())
102 }
103
104 pub fn as_str(&self) -> Option<&str> {
105 match self {
106 Variable::String(s) => Some(s.as_ref()),
107 _ => None,
108 }
109 }
110
111 pub fn as_rc_str(&self) -> Option<Rc<str>> {
112 match self {
113 Variable::String(s) => Some(Rc::from(s.as_str())),
114 _ => None,
115 }
116 }
117
118 pub fn as_sym(&self) -> Option<&Symbol> {
119 match self {
120 Variable::String(s) => Some(s),
121 _ => None,
122 }
123 }
124
125 pub fn as_array(&self) -> Option<RcCell<Vec<Variable>>> {
126 match self {
127 Variable::Array(arr) => Some(arr.clone()),
128 _ => None,
129 }
130 }
131
132 pub fn is_array(&self) -> bool {
133 match self {
134 Variable::Array(_) => true,
135 _ => false,
136 }
137 }
138
139 pub fn as_object(&self) -> Option<RcCell<VariableMap>> {
140 match self {
141 Variable::Object(obj) => Some(obj.clone()),
142 _ => None,
143 }
144 }
145
146 pub fn is_object(&self) -> bool {
147 match self {
148 Variable::Object(_) => true,
149 _ => false,
150 }
151 }
152
153 pub fn as_bool(&self) -> Option<bool> {
154 match self {
155 Variable::Bool(b) => Some(*b),
156 _ => None,
157 }
158 }
159
160 pub fn as_number(&self) -> Option<Decimal> {
161 match self {
162 Variable::Number(n) => Some(*n),
163 _ => None,
164 }
165 }
166
167 pub fn type_name(&self) -> &'static str {
168 match self {
169 Variable::Null => "null",
170 Variable::Bool(_) => "bool",
171 Variable::Number(_) => "number",
172 Variable::String(_) => "string",
173 Variable::Array(_) => "array",
174 Variable::Object(_) => "object",
175 Variable::Dynamic(d) => d.type_name(),
176 }
177 }
178
179 pub fn dynamic<T: DynamicVariable + 'static>(&self) -> Option<&T> {
180 match self {
181 Variable::Dynamic(d) => d.as_any().downcast_ref::<T>(),
182 _ => None,
183 }
184 }
185
186 pub fn to_value(&self) -> Value {
187 Value::from(self.shallow_clone())
188 }
189
190 pub fn dot(&self, key: &str) -> Option<Variable> {
191 key.split('.')
192 .try_fold(self.shallow_clone(), |var, part| match var {
193 Variable::Object(obj) => {
194 let reference = obj.borrow();
195 reference.get_str(part).map(|v| v.shallow_clone())
196 }
197 _ => None,
198 })
199 }
200
201 fn dot_head_detach(&self, key: &str) -> (Variable, Option<Variable>) {
202 let mut parts = Vec::from_iter(key.split('.'));
203 parts.pop();
204
205 let cloned_self = self.depth_clone(1);
206 let head = parts
207 .iter()
208 .try_fold(cloned_self.shallow_clone(), |var, part| match var {
209 Variable::Object(obj) => {
210 let mut obj_ref = obj.borrow_mut();
211 Some(match obj_ref.entry(Symbol::from(*part)) {
212 Entry::Occupied(mut occ) => {
213 let var = occ.get();
214 let new_obj = match var {
215 Variable::Object(_) => var.depth_clone(1),
216 _ => Variable::empty_object(),
217 };
218
219 occ.insert(new_obj.shallow_clone());
220 new_obj
221 }
222 Entry::Vacant(vac) => vac.insert(Self::empty_object()).shallow_clone(),
223 })
224 }
225 _ => None,
226 });
227
228 (cloned_self, head)
229 }
230
231 pub fn dot_remove(&self, key: &str) -> Option<Variable> {
232 let mut parts = key.split('.');
233 let last_part = parts.next_back()?;
234 let head = parts.try_fold(self.shallow_clone(), |var, part| match var {
235 Variable::Object(obj) => {
236 let mut obj_ref = obj.borrow_mut();
237 Some(match obj_ref.entry(Symbol::from(part)) {
238 Entry::Occupied(occ) => occ.get().shallow_clone(),
239 Entry::Vacant(vac) => vac.insert(Self::empty_object()).shallow_clone(),
240 })
241 }
242 _ => None,
243 })?;
244 let Variable::Object(object_ref) = head else {
245 return None;
246 };
247
248 let mut object = object_ref.borrow_mut();
249 object.remove_str(last_part)
250 }
251
252 pub fn dot_insert(&self, key: &str, variable: Variable) -> Option<Variable> {
253 let mut parts = key.split('.');
254 let last_part = parts.next_back()?;
255 let head = parts.try_fold(self.shallow_clone(), |var, part| match var {
256 Variable::Object(obj) => {
257 let mut obj_ref = obj.borrow_mut();
258 Some(match obj_ref.entry(Symbol::from(part)) {
259 Entry::Occupied(occ) => occ.get().shallow_clone(),
260 Entry::Vacant(vac) => vac.insert(Self::empty_object()).shallow_clone(),
261 })
262 }
263 _ => None,
264 })?;
265 let Variable::Object(object_ref) = head else {
266 return None;
267 };
268
269 let mut object = object_ref.borrow_mut();
270 object.insert(Symbol::from(last_part), variable)
271 }
272
273 pub fn dot_insert_detached(&self, key: &str, variable: Variable) -> Option<Variable> {
274 let last_part = key.split('.').last()?;
275 let (new_var, head_opt) = self.dot_head_detach(key);
276 let head = head_opt?;
277 let Variable::Object(object_ref) = head else {
278 return None;
279 };
280
281 let mut object = object_ref.borrow_mut();
282 object.insert(Symbol::from(last_part), variable);
283 Some(new_var)
284 }
285
286 pub fn merge(&mut self, patch: &Variable) -> Variable {
287 let _ = merge_variables(self, patch, true, MergeStrategy::InPlace);
288
289 self.shallow_clone()
290 }
291
292 pub fn merge_clone(&mut self, patch: &Variable) -> Variable {
293 let mut new_self = self.shallow_clone();
294
295 let _ = merge_variables(&mut new_self, patch, true, MergeStrategy::CloneOnWrite);
296 new_self
297 }
298
299 pub fn shallow_clone(&self) -> Self {
300 match self {
301 Variable::Null => Variable::Null,
302 Variable::Bool(b) => Variable::Bool(*b),
303 Variable::Number(n) => Variable::Number(*n),
304 Variable::String(s) => Variable::String(s.clone()),
305 Variable::Array(a) => Variable::Array(a.clone()),
306 Variable::Object(o) => Variable::Object(o.clone()),
307 Variable::Dynamic(d) => Variable::Dynamic(d.clone()),
308 }
309 }
310
311 pub fn deep_clone(&self) -> Self {
312 match self {
313 Variable::Array(a) => {
314 let arr = a.borrow();
315 Variable::from_array(arr.iter().map(|v| v.deep_clone()).collect())
316 }
317 Variable::Object(o) => {
318 let obj = o.borrow();
319 Variable::from_object(
320 obj.iter()
321 .map(|(k, v)| (k.clone(), v.deep_clone()))
322 .collect(),
323 )
324 }
325 _ => self.shallow_clone(),
326 }
327 }
328
329 pub fn depth_clone(&self, depth: usize) -> Self {
330 match depth.is_zero() {
331 true => self.shallow_clone(),
332 false => match self {
333 Variable::Array(a) => {
334 let arr = a.borrow();
335 Variable::from_array(arr.iter().map(|v| v.depth_clone(depth - 1)).collect())
336 }
337 Variable::Object(o) => {
338 let obj = o.borrow();
339 Variable::from_object(
340 obj.iter()
341 .map(|(k, v)| (k.clone(), v.depth_clone(depth - 1)))
342 .collect(),
343 )
344 }
345 _ => self.shallow_clone(),
346 },
347 }
348 }
349}
350
351impl Clone for Variable {
352 fn clone(&self) -> Self {
353 self.shallow_clone()
354 }
355}
356
357#[derive(Copy, Clone)]
358enum MergeStrategy {
359 InPlace,
360 CloneOnWrite,
361}
362
363fn merge_variables(
364 doc: &mut Variable,
365 patch: &Variable,
366 top_level: bool,
367 strategy: MergeStrategy,
368) -> bool {
369 if patch.is_array() && top_level {
370 *doc = patch.shallow_clone();
371 return true;
372 }
373
374 if !patch.is_object() && top_level {
375 return false;
376 }
377
378 if doc.is_object() && patch.is_object() {
379 let doc_ref = doc.as_object().unwrap();
380 let patch_ref = patch.as_object().unwrap();
381 if RcCell::ptr_eq(&doc_ref, &patch_ref) {
382 return false;
383 }
384
385 let patch = patch_ref.borrow();
386 match strategy {
387 MergeStrategy::InPlace => {
388 let mut map = doc_ref.borrow_mut();
389 for (key, value) in patch.deref() {
390 if value == &Variable::Null {
391 map.remove(key);
392 } else {
393 let entry = map.entry(key.clone()).or_insert(Variable::Null);
394 merge_variables(entry, value, false, strategy);
395 }
396 }
397
398 return true;
399 }
400 MergeStrategy::CloneOnWrite => {
401 let mut changed = false;
402 let mut new_map: Option<VariableMap> = None;
403
404 for (key, value) in patch.deref() {
405 let map = if let Some(ref mut m) = new_map {
407 m
408 } else {
409 let m = doc_ref.borrow().clone();
410 new_map = Some(m);
411 new_map.as_mut().unwrap()
412 };
413
414 if value == &Variable::Null {
415 if map.remove(key).is_some() {
417 changed = true;
418 }
419 } else {
420 let entry = map.entry(key.clone()).or_insert(Variable::Null);
422 if merge_variables(entry, value, false, strategy) {
423 changed = true;
424 }
425 }
426 }
427
428 if changed {
430 if let Some(new_map) = new_map {
431 *doc = Variable::Object(Rc::new(RefCell::new(new_map)));
432 }
433 return true;
434 }
435
436 return false;
437 }
438 }
439 } else {
440 let new_value = patch.shallow_clone();
441 if *doc != new_value {
442 *doc = new_value;
443 return true;
444 }
445
446 return false;
447 }
448}
449
450impl Default for Variable {
451 fn default() -> Self {
452 Variable::Null
453 }
454}
455
456impl Display for Variable {
457 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
458 match self {
459 Variable::Null => write!(f, "null"),
460 Variable::Bool(b) => match *b {
461 true => write!(f, "true"),
462 false => write!(f, "false"),
463 },
464 Variable::Number(n) => write!(f, "{n}"),
465 Variable::String(s) => write!(f, "\"{s}\""),
466 Variable::Array(arr) => {
467 let arr = arr.borrow();
468 let s = arr
469 .iter()
470 .map(|v| v.to_string())
471 .collect::<Vec<String>>()
472 .join(",");
473 write!(f, "[{s}]")
474 }
475 Variable::Object(obj) => {
476 let obj = obj.borrow();
477 let s = obj
478 .iter()
479 .map(|(k, v)| format!("\"{k}\":{v}"))
480 .collect::<Vec<String>>()
481 .join(",");
482
483 write!(f, "{{{s}}}")
484 }
485 Variable::Dynamic(d) => write!(f, "{d}"),
486 }
487 }
488}
489
490impl Debug for Variable {
491 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
492 write!(f, "{}", self)
493 }
494}
495
496impl PartialEq for Variable {
497 fn eq(&self, other: &Self) -> bool {
498 match (&self, &other) {
499 (Variable::Null, Variable::Null) => true,
500 (Variable::Bool(b1), Variable::Bool(b2)) => b1 == b2,
501 (Variable::Number(n1), Variable::Number(n2)) => n1 == n2,
502 (Variable::String(s1), Variable::String(s2)) => s1.as_str() == s2.as_str(),
503 (Variable::Array(a1), Variable::Array(a2)) => a1 == a2,
504 (Variable::Object(obj1), Variable::Object(obj2)) => obj1 == obj2,
505 (Variable::Dynamic(d1), Variable::Dynamic(d2)) => Rc::ptr_eq(d1, d2),
506 _ => false,
507 }
508 }
509}
510
511impl Eq for Variable {}
512
513#[cfg(test)]
514mod tests {
515 use crate::variable::Variable;
516 use rust_decimal_macros::dec;
517 use serde_json::json;
518
519 #[test]
520 fn insert_detached() {
521 let some_data: Variable = json!({ "customer": { "firstName": "John" }}).into();
522
523 let a_a = some_data
524 .dot_insert_detached("a.a", Variable::Number(dec!(1)))
525 .unwrap();
526 let a_b = a_a
527 .dot_insert_detached("a.b", Variable::Number(dec!(2)))
528 .unwrap();
529 let a_c = a_b
530 .dot_insert_detached("a.c", Variable::Number(dec!(3)))
531 .unwrap();
532
533 assert_eq!(a_a.dot("a"), Some(Variable::from(json!({ "a": 1 }))));
534 assert_eq!(
535 a_b.dot("a"),
536 Some(Variable::from(json!({ "a": 1, "b": 2 })))
537 );
538 assert_eq!(
539 a_c.dot("a"),
540 Some(Variable::from(json!({ "a": 1, "b": 2, "c": 3 })))
541 );
542 }
543}