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