zen_expression/variable/
conv.rs

1use crate::variable::Variable;
2use crate::vm::helpers::date_time;
3use crate::vm::VMError;
4use chrono::NaiveDateTime;
5use rust_decimal::prelude::ToPrimitive;
6use rust_decimal::Decimal;
7use serde_json::{Number, Value};
8use std::rc::Rc;
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                Variable::Number(Decimal::from_str_exact(n.as_str()).expect("Allowed number"))
17            }
18            Value::String(s) => Variable::String(Rc::from(s.as_str())),
19            Value::Array(arr) => {
20                Variable::from_array(arr.into_iter().map(Variable::from).collect())
21            }
22            Value::Object(obj) => Variable::from_object(
23                obj.into_iter()
24                    .map(|(k, v)| (Rc::from(k.as_str()), Variable::from(v)))
25                    .collect(),
26            ),
27        }
28    }
29}
30
31impl From<&Value> for Variable {
32    fn from(value: &Value) -> Self {
33        match value {
34            Value::Null => Variable::Null,
35            Value::Bool(b) => Variable::Bool(*b),
36            Value::Number(n) => {
37                Variable::Number(Decimal::from_str_exact(n.as_str()).expect("Allowed number"))
38            }
39            Value::String(s) => Variable::String(Rc::from(s.as_str())),
40            Value::Array(arr) => Variable::from_array(arr.iter().map(Variable::from).collect()),
41            Value::Object(obj) => Variable::from_object(
42                obj.iter()
43                    .map(|(k, v)| (Rc::from(k.as_str()), Variable::from(v)))
44                    .collect(),
45            ),
46        }
47    }
48}
49
50impl From<Variable> for Value {
51    fn from(value: Variable) -> Self {
52        match value {
53            Variable::Null => Value::Null,
54            Variable::Bool(b) => Value::Bool(b),
55            Variable::Number(n) => Value::Number(Number::from_string_unchecked(n.to_string())),
56            Variable::String(s) => Value::String(s.to_string()),
57            Variable::Array(arr) => {
58                let vec = Rc::try_unwrap(arr)
59                    .map(|a| a.into_inner())
60                    .unwrap_or_else(|s| {
61                        let borrowed = s.borrow();
62                        borrowed.clone()
63                    });
64
65                Value::Array(vec.into_iter().map(Value::from).collect())
66            }
67            Variable::Object(obj) => {
68                let hmap = Rc::try_unwrap(obj)
69                    .map(|a| a.into_inner())
70                    .unwrap_or_else(|s| {
71                        let borrowed = s.borrow();
72                        borrowed.clone()
73                    });
74
75                Value::Object(
76                    hmap.into_iter()
77                        .map(|(k, v)| (k.to_string(), Value::from(v)))
78                        .collect(),
79                )
80            }
81            Variable::Dynamic(d) => d.to_value(),
82        }
83    }
84}
85
86impl TryFrom<&Variable> for NaiveDateTime {
87    type Error = VMError;
88
89    fn try_from(value: &Variable) -> Result<Self, Self::Error> {
90        match value {
91            Variable::String(a) => date_time(a),
92            #[allow(deprecated)]
93            Variable::Number(a) => NaiveDateTime::from_timestamp_opt(
94                a.to_i64().ok_or_else(|| VMError::OpcodeErr {
95                    opcode: "DateManipulation".into(),
96                    message: "Failed to extract date".into(),
97                })?,
98                0,
99            )
100            .ok_or_else(|| VMError::ParseDateTimeErr {
101                timestamp: a.to_string(),
102            }),
103            _ => Err(VMError::OpcodeErr {
104                opcode: "DateManipulation".into(),
105                message: "Unsupported type".into(),
106            }),
107        }
108    }
109}