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