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