mf_expression/variable/
de.rs

1use crate::variable::Variable;
2use ahash::{HashMap, HashMapExt};
3use rust_decimal::prelude::FromPrimitive;
4use rust_decimal::Decimal;
5use serde::de::{DeserializeSeed, Error, MapAccess, SeqAccess, Unexpected, Visitor};
6use serde::{Deserialize, Deserializer};
7use std::fmt::Formatter;
8use std::marker::PhantomData;
9use std::ops::Deref;
10use std::rc::Rc;
11
12struct VariableVisitor;
13
14pub(super) const NUMBER_TOKEN: &str = "$serde_json::private::Number";
15
16impl<'de> Visitor<'de> for VariableVisitor {
17    type Value = Variable;
18
19    fn expecting(
20        &self,
21        formatter: &mut Formatter,
22    ) -> std::fmt::Result {
23        formatter.write_str("A valid type")
24    }
25
26    fn visit_bool<E>(
27        self,
28        v: bool,
29    ) -> Result<Self::Value, E>
30    where
31        E: Error,
32    {
33        Ok(Variable::Bool(v))
34    }
35
36    fn visit_i64<E>(
37        self,
38        v: i64,
39    ) -> Result<Self::Value, E>
40    where
41        E: Error,
42    {
43        Ok(Variable::Number(Decimal::from_i64(v).ok_or_else(|| {
44            Error::invalid_value(Unexpected::Signed(v), &self)
45        })?))
46    }
47
48    fn visit_u64<E>(
49        self,
50        v: u64,
51    ) -> Result<Self::Value, E>
52    where
53        E: Error,
54    {
55        Ok(Variable::Number(Decimal::from_u64(v).ok_or_else(|| {
56            Error::invalid_value(Unexpected::Unsigned(v), &self)
57        })?))
58    }
59
60    fn visit_f64<E>(
61        self,
62        v: f64,
63    ) -> Result<Self::Value, E>
64    where
65        E: Error,
66    {
67        Ok(Variable::Number(Decimal::from_f64(v).ok_or_else(|| {
68            Error::invalid_value(Unexpected::Float(v), &self)
69        })?))
70    }
71
72    fn visit_str<E>(
73        self,
74        v: &str,
75    ) -> Result<Self::Value, E>
76    where
77        E: Error,
78    {
79        Ok(Variable::String(Rc::from(v)))
80    }
81
82    fn visit_unit<E>(self) -> Result<Self::Value, E>
83    where
84        E: Error,
85    {
86        Ok(Variable::Null)
87    }
88
89    fn visit_seq<A>(
90        self,
91        mut seq: A,
92    ) -> Result<Self::Value, A::Error>
93    where
94        A: SeqAccess<'de>,
95    {
96        let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or_default());
97        while let Some(value) = seq.next_element_seed(VariableDeserializer)? {
98            vec.push(value);
99        }
100
101        Ok(Variable::from_array(vec))
102    }
103
104    fn visit_map<A>(
105        self,
106        mut map: A,
107    ) -> Result<Self::Value, A::Error>
108    where
109        A: MapAccess<'de>,
110    {
111        let mut m = HashMap::with_capacity(map.size_hint().unwrap_or_default());
112        let mut first = true;
113
114        while let Some((key, value)) =
115            map.next_entry_seed(PhantomData::<Rc<str>>, VariableDeserializer)?
116        {
117            if first && key.deref() == NUMBER_TOKEN {
118                let str = value.as_str().ok_or_else(|| {
119                    Error::custom("failed to deserialize number")
120                })?;
121
122                return Ok(Variable::Number(
123                    Decimal::from_str_exact(str)
124                        .or_else(|_| Decimal::from_scientific(str))
125                        .map_err(|_| Error::custom("invalid number"))?,
126                ));
127            }
128
129            m.insert(key, value);
130            first = false;
131        }
132
133        Ok(Variable::from_object(m))
134    }
135}
136
137pub struct VariableDeserializer;
138
139impl<'de> DeserializeSeed<'de> for VariableDeserializer {
140    type Value = Variable;
141
142    fn deserialize<D>(
143        self,
144        deserializer: D,
145    ) -> Result<Self::Value, D::Error>
146    where
147        D: Deserializer<'de>,
148    {
149        deserializer.deserialize_any(VariableVisitor)
150    }
151}
152
153impl<'de> Deserialize<'de> for Variable {
154    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
155    where
156        D: Deserializer<'de>,
157    {
158        deserializer.deserialize_any(VariableVisitor)
159    }
160}