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