spo_rhai/serde/
deserialize.rs1use 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}