Skip to main content

zen_types/variable/
conv.rs

1use crate::variable::Variable;
2use rust_decimal::Decimal;
3#[cfg(not(feature = "arbitrary_precision"))]
4use rust_decimal::prelude::FromPrimitive;
5use serde_json::{Number, Value};
6use std::rc::Rc;
7#[cfg(not(feature = "arbitrary_precision"))]
8use std::str::FromStr;
9
10impl From<Value> for Variable {
11    fn from(value: Value) -> Self {
12        match value {
13            Value::Null => Variable::Null,
14            Value::Bool(b) => Variable::Bool(b),
15            Value::Number(n) => {
16                #[cfg(feature = "arbitrary_precision")]
17                {
18                    Variable::Number(
19                        Decimal::from_str_exact(n.as_str())
20                            .or_else(|_| Decimal::from_scientific(n.as_str()))
21                            .expect("Allowed number"),
22                    )
23                }
24
25                #[cfg(not(feature = "arbitrary_precision"))]
26                {
27                    if let Some(n) = n.as_u64() {
28                        return Variable::Number(n.into());
29                    }
30
31                    if let Some(n) = n.as_i64() {
32                        return Variable::Number(n.into());
33                    }
34
35                    if let Some(n) = n.as_f64() {
36                        return Variable::Number(Decimal::from_f64(n).expect("Allowed number"));
37                    }
38
39                    unreachable!(
40                        "serde_json::Number is always u64, i64, or f64 without arbitrary_precision"
41                    )
42                }
43            }
44            Value::String(s) => Variable::String(Rc::from(s.as_str())),
45            Value::Array(arr) => {
46                Variable::from_array(arr.into_iter().map(Variable::from).collect())
47            }
48            Value::Object(obj) => Variable::from_object(
49                obj.into_iter()
50                    .map(|(k, v)| (Rc::from(k.as_str()), Variable::from(v)))
51                    .collect(),
52            ),
53        }
54    }
55}
56
57impl From<&Value> for Variable {
58    fn from(value: &Value) -> Self {
59        match value {
60            Value::Null => Variable::Null,
61            Value::Bool(b) => Variable::Bool(*b),
62            Value::Number(n) => {
63                #[cfg(feature = "arbitrary_precision")]
64                {
65                    Variable::Number(
66                        Decimal::from_str_exact(n.as_str())
67                            .or_else(|_| Decimal::from_scientific(n.as_str()))
68                            .expect("Allowed number"),
69                    )
70                }
71
72                #[cfg(not(feature = "arbitrary_precision"))]
73                {
74                    if let Some(u) = n.as_u64() {
75                        return Variable::Number(u.into());
76                    }
77
78                    if let Some(i) = n.as_i64() {
79                        return Variable::Number(i.into());
80                    }
81
82                    if let Some(f) = n.as_f64() {
83                        return Variable::Number(Decimal::from_f64(f).expect("Allowed number"));
84                    }
85
86                    unreachable!(
87                        "serde_json::Number is always u64, i64, or f64 without arbitrary_precision"
88                    );
89                }
90            }
91            Value::String(s) => Variable::String(Rc::from(s.as_str())),
92            Value::Array(arr) => Variable::from_array(arr.iter().map(Variable::from).collect()),
93            Value::Object(obj) => Variable::from_object(
94                obj.iter()
95                    .map(|(k, v)| (Rc::from(k.as_str()), Variable::from(v)))
96                    .collect(),
97            ),
98        }
99    }
100}
101
102impl From<Variable> for Value {
103    fn from(value: Variable) -> Self {
104        match value {
105            Variable::Null => Value::Null,
106            Variable::Bool(b) => Value::Bool(b),
107            Variable::Number(n) => {
108                #[cfg(feature = "arbitrary_precision")]
109                {
110                    Value::Number(Number::from_string_unchecked(n.normalize().to_string()))
111                }
112                #[cfg(not(feature = "arbitrary_precision"))]
113                {
114                    Value::Number(
115                        Number::from_str(n.normalize().to_string().as_str())
116                            .expect("Allowed number"),
117                    )
118                }
119            }
120            Variable::String(s) => Value::String(s.to_string()),
121            Variable::Array(arr) => {
122                let vec = Rc::try_unwrap(arr)
123                    .map(|a| a.into_inner())
124                    .unwrap_or_else(|s| {
125                        let borrowed = s.borrow();
126                        borrowed.clone()
127                    });
128
129                Value::Array(vec.into_iter().map(Value::from).collect())
130            }
131            Variable::Object(obj) => {
132                let hmap = Rc::try_unwrap(obj)
133                    .map(|a| a.into_inner())
134                    .unwrap_or_else(|s| {
135                        let borrowed = s.borrow();
136                        borrowed.clone()
137                    });
138
139                Value::Object(
140                    hmap.into_iter()
141                        .map(|(k, v)| (k.to_string(), Value::from(v)))
142                        .collect(),
143                )
144            }
145            Variable::Dynamic(d) => d.to_value(),
146        }
147    }
148}