spo_rhai/serde/
deserialize.rs

1//! Implementations of [`serde::Deserialize`].
2
3use crate::{Dynamic, Identifier, ImmutableString, Scope, INT};
4use serde::{
5    de::{Error, SeqAccess, Visitor},
6    Deserialize, Deserializer,
7};
8use std::fmt;
9#[cfg(feature = "no_std")]
10use std::prelude::v1::*;
11
12#[cfg(feature = "decimal")]
13use num_traits::FromPrimitive;
14
15struct DynamicVisitor;
16
17impl<'de> Visitor<'de> for DynamicVisitor {
18    type Value = Dynamic;
19
20    #[cold]
21    #[inline(never)]
22    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
23        f.write_str("any type that can be converted into a Dynamic")
24    }
25    #[inline(always)]
26    fn visit_bool<E: Error>(self, v: bool) -> Result<Self::Value, E> {
27        Ok(v.into())
28    }
29    #[inline(always)]
30    fn visit_i8<E: Error>(self, v: i8) -> Result<Self::Value, E> {
31        Ok(INT::from(v).into())
32    }
33    #[inline(always)]
34    fn visit_i16<E: Error>(self, v: i16) -> Result<Self::Value, E> {
35        Ok(INT::from(v).into())
36    }
37    #[inline(always)]
38    fn visit_i32<E: Error>(self, v: i32) -> Result<Self::Value, E> {
39        Ok(INT::from(v).into())
40    }
41    #[inline]
42    fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
43        #[cfg(not(feature = "only_i32"))]
44        return Ok(v.into());
45
46        #[cfg(feature = "only_i32")]
47        if v <= INT::MAX as i64 {
48            return Ok(Dynamic::from(v as INT));
49        }
50
51        #[allow(unreachable_code)]
52        {
53            #[cfg(feature = "decimal")]
54            if let Some(n) = rust_decimal::Decimal::from_i64(v) {
55                return Ok(Dynamic::from_decimal(n));
56            }
57
58            #[cfg(not(feature = "no_float"))]
59            return Ok(Dynamic::from_float(v as crate::FLOAT));
60
61            Err(Error::custom(format!("integer number too large: {v}")))
62        }
63    }
64    #[inline]
65    fn visit_i128<E: Error>(self, v: i128) -> Result<Self::Value, E> {
66        if v <= i128::from(INT::MAX) {
67            return Ok(Dynamic::from(v as INT));
68        }
69
70        #[allow(unreachable_code)]
71        {
72            #[cfg(feature = "decimal")]
73            if let Some(n) = rust_decimal::Decimal::from_i128(v) {
74                return Ok(Dynamic::from_decimal(n));
75            }
76
77            #[cfg(not(feature = "no_float"))]
78            return Ok(Dynamic::from_float(v as crate::FLOAT));
79
80            Err(Error::custom(format!("integer number too large: {v}")))
81        }
82    }
83    #[inline(always)]
84    fn visit_u8<E: Error>(self, v: u8) -> Result<Self::Value, E> {
85        Ok(INT::from(v).into())
86    }
87    #[inline(always)]
88    fn visit_u16<E: Error>(self, v: u16) -> Result<Self::Value, E> {
89        Ok(INT::from(v).into())
90    }
91    #[inline]
92    fn visit_u32<E: Error>(self, v: u32) -> Result<Self::Value, E> {
93        #[cfg(not(feature = "only_i32"))]
94        return Ok(Dynamic::from(v as INT));
95
96        #[cfg(feature = "only_i32")]
97        if v <= INT::MAX as u32 {
98            return Ok(Dynamic::from(v as INT));
99        }
100
101        #[allow(unreachable_code)]
102        {
103            #[cfg(feature = "decimal")]
104            if let Some(n) = rust_decimal::Decimal::from_u32(v) {
105                return Ok(Dynamic::from_decimal(n));
106            }
107
108            #[cfg(not(feature = "no_float"))]
109            return Ok(Dynamic::from_float(v as crate::FLOAT));
110
111            Err(Error::custom(format!("integer number too large: {v}")))
112        }
113    }
114    #[inline]
115    fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
116        if v <= INT::MAX as u64 {
117            return Ok(Dynamic::from(v as INT));
118        }
119
120        #[cfg(feature = "decimal")]
121        if let Some(n) = rust_decimal::Decimal::from_u64(v) {
122            return Ok(Dynamic::from_decimal(n));
123        }
124
125        #[cfg(not(feature = "no_float"))]
126        return Ok(Dynamic::from_float(v as crate::FLOAT));
127
128        #[allow(unreachable_code)]
129        Err(Error::custom(format!("integer number too large: {v}")))
130    }
131    #[inline]
132    fn visit_u128<E: Error>(self, v: u128) -> Result<Self::Value, E> {
133        if v <= INT::MAX as u128 {
134            return Ok(Dynamic::from(v as INT));
135        }
136
137        #[cfg(feature = "decimal")]
138        if let Some(n) = rust_decimal::Decimal::from_u128(v) {
139            return Ok(Dynamic::from_decimal(n));
140        }
141
142        #[cfg(not(feature = "no_float"))]
143        return Ok(Dynamic::from_float(v as crate::FLOAT));
144
145        #[allow(unreachable_code)]
146        Err(Error::custom(format!("integer number too large: {v}")))
147    }
148
149    #[cfg(not(feature = "no_float"))]
150    #[inline(always)]
151    fn visit_f32<E: Error>(self, v: f32) -> Result<Self::Value, E> {
152        #[cfg(not(feature = "no_float"))]
153        return Ok((v as crate::FLOAT).into());
154
155        #[allow(unreachable_code)]
156        {
157            #[cfg(feature = "decimal")]
158            if let Some(n) = rust_decimal::Decimal::from_f32(v) {
159                return Ok(Dynamic::from_decimal(n));
160            }
161
162            Err(Error::custom(format!(
163                "floating-point number is not supported: {v}"
164            )))
165        }
166    }
167    #[cfg(not(feature = "no_float"))]
168    #[inline(always)]
169    fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
170        #[cfg(not(feature = "no_float"))]
171        return Ok((v as crate::FLOAT).into());
172
173        #[allow(unreachable_code)]
174        {
175            #[cfg(feature = "decimal")]
176            if let Some(n) = rust_decimal::Decimal::from_f64(v) {
177                return Ok(Dynamic::from_decimal(n));
178            }
179
180            Err(Error::custom(format!(
181                "floating-point number is not supported: {v}"
182            )))
183        }
184    }
185
186    #[cfg(feature = "no_float")]
187    #[cfg(feature = "decimal")]
188    #[inline]
189    fn visit_f32<E: Error>(self, v: f32) -> Result<Self::Value, E> {
190        use std::convert::TryFrom;
191
192        rust_decimal::Decimal::try_from(v)
193            .map(|v| v.into())
194            .map_err(Error::custom)
195    }
196    #[cfg(feature = "no_float")]
197    #[cfg(feature = "decimal")]
198    #[inline]
199    fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
200        use std::convert::TryFrom;
201
202        rust_decimal::Decimal::try_from(v)
203            .map(|v| v.into())
204            .map_err(Error::custom)
205    }
206
207    #[inline(always)]
208    fn visit_char<E: Error>(self, v: char) -> Result<Self::Value, E> {
209        Ok(v.into())
210    }
211    #[inline(always)]
212    fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
213        Ok(v.into())
214    }
215    #[inline(always)]
216    fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
217        Ok(v.into())
218    }
219    #[cfg(not(feature = "no_index"))]
220    #[inline(always)]
221    fn visit_bytes<E: Error>(self, v: &[u8]) -> Result<Self::Value, E> {
222        Ok(Dynamic::from_blob(v.to_vec()))
223    }
224
225    #[inline(always)]
226    fn visit_unit<E: Error>(self) -> Result<Self::Value, E> {
227        Ok(Dynamic::UNIT)
228    }
229
230    #[inline(always)]
231    fn visit_newtype_struct<D: Deserializer<'de>>(self, de: D) -> Result<Self::Value, D::Error> {
232        Deserialize::deserialize(de)
233    }
234
235    #[cfg(not(feature = "no_index"))]
236    fn visit_seq<A: serde::de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
237        let mut arr = crate::Array::new();
238
239        while let Some(v) = seq.next_element()? {
240            arr.push(v);
241        }
242
243        Ok(arr.into())
244    }
245
246    #[cfg(not(feature = "no_object"))]
247    fn visit_map<M: serde::de::MapAccess<'de>>(self, mut map: M) -> Result<Self::Value, M::Error> {
248        let mut m = crate::Map::new();
249
250        while let Some((k, v)) = map.next_entry()? {
251            m.insert(k, v);
252        }
253
254        Ok(m.into())
255    }
256}
257
258impl<'de> Deserialize<'de> for Dynamic {
259    #[inline(always)]
260    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
261        deserializer.deserialize_any(DynamicVisitor)
262    }
263}
264
265impl<'de> Deserialize<'de> for ImmutableString {
266    #[inline(always)]
267    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
268        let s: String = Deserialize::deserialize(deserializer)?;
269        Ok(s.into())
270    }
271}
272
273impl<'de> Deserialize<'de> for Scope<'de> {
274    #[inline(always)]
275    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
276        #[derive(Debug, Clone, Hash, Deserialize)]
277        struct ScopeEntry {
278            pub name: Identifier,
279            pub value: Dynamic,
280            #[serde(default)]
281            pub is_constant: bool,
282        }
283
284        struct VecVisitor;
285
286        impl<'de> Visitor<'de> for VecVisitor {
287            type Value = Scope<'static>;
288
289            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
290                formatter.write_str("a sequence")
291            }
292
293            #[inline]
294            fn visit_seq<A>(self, mut access: A) -> Result<Self::Value, A::Error>
295            where
296                A: SeqAccess<'de>,
297            {
298                let mut scope = access
299                    .size_hint()
300                    .map_or_else(Scope::new, Scope::with_capacity);
301
302                while let Some(ScopeEntry {
303                    name,
304                    value,
305                    is_constant,
306                }) = access.next_element()?
307                {
308                    if is_constant {
309                        scope.push_constant_dynamic(name, value);
310                    } else {
311                        scope.push_dynamic(name, value);
312                    }
313                }
314
315                Ok(scope)
316            }
317        }
318
319        deserializer.deserialize_seq(VecVisitor)
320    }
321}