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