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