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