smart_config/de/
deserializer.rs

1//! `serde`-compatible deserializer based on a value with origin.
2
3use std::sync::Arc;
4
5use serde::{
6    Deserialize, Deserializer,
7    de::{
8        self, DeserializeSeed, Error as DeError, IntoDeserializer,
9        value::{MapDeserializer, SeqDeserializer},
10    },
11};
12
13use crate::{
14    error::ErrorWithOrigin,
15    utils::EnumVariant,
16    value::{Map, StrValue, Value, ValueOrigin, WithOrigin},
17};
18
19/// Available deserialization options.
20#[derive(Debug, Clone, Default)]
21pub struct DeserializerOptions {
22    /// Enables coercion of variant names between cases, e.g. from `SHOUTING_CASE` to `shouting_case`.
23    pub coerce_variant_names: bool,
24}
25
26impl WithOrigin {
27    #[cold]
28    pub(super) fn invalid_type(&self, expected: &str) -> ErrorWithOrigin {
29        let actual = match &self.inner {
30            Value::Null => de::Unexpected::Unit,
31            Value::Bool(value) => de::Unexpected::Bool(*value),
32            Value::Number(value) => {
33                if let Some(value) = value.as_u64() {
34                    de::Unexpected::Unsigned(value)
35                } else if let Some(value) = value.as_i64() {
36                    de::Unexpected::Signed(value)
37                } else if let Some(value) = value.as_f64() {
38                    de::Unexpected::Float(value)
39                } else {
40                    de::Unexpected::Other("number")
41                }
42            }
43            Value::String(StrValue::Plain(s)) => de::Unexpected::Str(s),
44            Value::String(StrValue::Secret(_)) => de::Unexpected::Other("secret"),
45            Value::Array(_) => de::Unexpected::Seq,
46            Value::Object(_) => de::Unexpected::Map,
47        };
48        ErrorWithOrigin::json(
49            DeError::invalid_type(actual, &expected),
50            self.origin.clone(),
51        )
52    }
53}
54
55macro_rules! parse_int_value {
56    ($($ty:ident => $method:ident,)*) => {
57        $(
58        fn $method<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
59            let result = match self.value() {
60                Value::String(s) => {
61                    match s.expose().parse::<$ty>() {
62                        Ok(val) => val.into_deserializer().$method(visitor),
63                        Err(err) => {
64                            let err = DeError::custom(format_args!("{err} while parsing {} value '{s}'", stringify!($ty)));
65                            return Err(self.enrich_err(err));
66                        }
67                    }
68                }
69                Value::Number(number) => number.deserialize_any(visitor).map_err(|err| self.enrich_err(err.into())),
70                _ => return Err(self.invalid_type(&format!("{} number", stringify!($ty)))),
71            };
72            result.map_err(|err| err.set_origin_if_unset(&self.value.origin))
73        }
74        )*
75    }
76}
77
78#[derive(Debug, Clone, Copy)]
79pub struct ValueDeserializer<'a> {
80    value: &'a WithOrigin,
81    options: &'a DeserializerOptions,
82}
83
84impl<'a> ValueDeserializer<'a> {
85    pub(super) fn new(value: &'a WithOrigin, options: &'a DeserializerOptions) -> Self {
86        Self { value, options }
87    }
88
89    pub(super) fn value(&self) -> &'a Value {
90        &self.value.inner
91    }
92
93    pub(super) fn origin(&self) -> &Arc<ValueOrigin> {
94        &self.value.origin
95    }
96
97    pub(super) fn enrich_err(&self, err: serde_json::Error) -> ErrorWithOrigin {
98        ErrorWithOrigin::json(err, self.value.origin.clone())
99    }
100
101    pub(super) fn invalid_type(&self, expected: &str) -> ErrorWithOrigin {
102        self.value.invalid_type(expected)
103    }
104
105    fn parse_array<'de, V: de::Visitor<'de>>(
106        &self,
107        array: &[WithOrigin],
108        visitor: V,
109    ) -> Result<V::Value, ErrorWithOrigin> {
110        let mut deserializer = SeqDeserializer::new(
111            array
112                .iter()
113                .map(|val| ValueDeserializer::new(val, self.options)),
114        );
115        let seq = visitor.visit_seq(&mut deserializer)?;
116        deserializer.end()?;
117        Ok(seq)
118    }
119
120    fn parse_object<'de, V: de::Visitor<'de>>(
121        &self,
122        object: &Map,
123        visitor: V,
124    ) -> Result<V::Value, ErrorWithOrigin> {
125        let mut deserializer = MapDeserializer::new(
126            object
127                .iter()
128                .map(|(key, value)| (key.as_str(), ValueDeserializer::new(value, self.options))),
129        );
130        let map = visitor.visit_map(&mut deserializer)?;
131        deserializer.end()?;
132        Ok(map)
133    }
134}
135
136impl<'de> Deserializer<'de> for ValueDeserializer<'_> {
137    type Error = ErrorWithOrigin;
138
139    fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
140        let result = match self.value() {
141            Value::Null => visitor.visit_none(),
142            Value::Bool(value) => visitor.visit_bool(*value),
143            Value::Number(value) => value
144                .deserialize_any(visitor)
145                .map_err(|err| self.enrich_err(err)),
146            Value::String(value) => visitor.visit_str(value.expose()),
147            Value::Array(array) => self.parse_array(array, visitor),
148            Value::Object(object) => self.parse_object(object, visitor),
149        };
150        result.map_err(|err| err.set_origin_if_unset(&self.value.origin))
151    }
152
153    fn deserialize_option<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
154        let result = match self.value() {
155            Value::Null => visitor.visit_none(),
156            _ => visitor.visit_some(self),
157        };
158        result.map_err(|err| err.set_origin_if_unset(&self.value.origin))
159    }
160
161    fn deserialize_newtype_struct<V: de::Visitor<'de>>(
162        self,
163        _name: &'static str,
164        visitor: V,
165    ) -> Result<V::Value, Self::Error> {
166        visitor
167            .visit_newtype_struct(self)
168            .map_err(|err| err.set_origin_if_unset(&self.value.origin))
169    }
170
171    fn deserialize_seq<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
172        let result = match self.value() {
173            Value::Array(array) => self.parse_array(array, visitor),
174            _ => Err(self.invalid_type("array")),
175        };
176        result.map_err(|err| err.set_origin_if_unset(&self.value.origin))
177    }
178
179    fn deserialize_tuple<V: de::Visitor<'de>>(
180        self,
181        _len: usize,
182        visitor: V,
183    ) -> Result<V::Value, Self::Error> {
184        self.deserialize_seq(visitor)
185            .map_err(|err| err.set_origin_if_unset(&self.value.origin))
186    }
187
188    fn deserialize_tuple_struct<V: de::Visitor<'de>>(
189        self,
190        _name: &'static str,
191        _len: usize,
192        visitor: V,
193    ) -> Result<V::Value, Self::Error> {
194        self.deserialize_seq(visitor)
195            .map_err(|err| err.set_origin_if_unset(&self.value.origin))
196    }
197
198    fn deserialize_map<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
199        let result = match self.value() {
200            Value::Object(object) => self.parse_object(object, visitor),
201            _ => Err(self.invalid_type("object")),
202        };
203        result.map_err(|err| err.set_origin_if_unset(&self.value.origin))
204    }
205
206    fn deserialize_struct<V: de::Visitor<'de>>(
207        self,
208        _name: &'static str,
209        _fields: &'static [&'static str],
210        visitor: V,
211    ) -> Result<V::Value, Self::Error> {
212        let result = match self.value() {
213            Value::Array(array) => self.parse_array(array, visitor),
214            Value::Object(object) => self.parse_object(object, visitor),
215            _ => Err(self.invalid_type("array or object")),
216        };
217        result.map_err(|err| err.set_origin_if_unset(&self.value.origin))
218    }
219
220    fn deserialize_enum<V: de::Visitor<'de>>(
221        self,
222        _name: &'static str,
223        variants: &'static [&'static str],
224        visitor: V,
225    ) -> Result<V::Value, Self::Error> {
226        let (mut variant, value) = match self.value() {
227            Value::Object(object) if object.len() == 1 => {
228                let (variant, value) = object.iter().next().unwrap();
229                (variant.as_str(), Some(value))
230            }
231            Value::String(s) => (s.expose(), None),
232            _ => return Err(self.invalid_type("string or object with single key")),
233        };
234
235        if self.options.coerce_variant_names {
236            if let Some(parsed) = EnumVariant::new(variant) {
237                if let Some(expected_variant) = parsed.try_match(variants) {
238                    variant = expected_variant;
239                }
240            }
241        }
242
243        visitor
244            .visit_enum(EnumDeserializer {
245                variant,
246                inner: VariantDeserializer {
247                    value,
248                    options: self.options,
249                    parent_origin: self.value.origin.clone(),
250                },
251            })
252            .map_err(|err| err.set_origin_if_unset(&self.value.origin))
253    }
254
255    // Primitive values
256
257    fn deserialize_bool<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
258        let result = match self.value() {
259            Value::Bool(value) => visitor.visit_bool(*value),
260            Value::String(s) => match s.expose().parse::<bool>() {
261                Ok(val) => visitor.visit_bool(val),
262                Err(err) => {
263                    let err =
264                        DeError::custom(format_args!("{err} while parsing value '{s}' as boolean"));
265                    return Err(self.enrich_err(err));
266                }
267            },
268            _ => return Err(self.invalid_type("boolean or boolean-like string")),
269        };
270        result.map_err(|err: serde_json::Error| self.enrich_err(err))
271    }
272
273    parse_int_value! {
274        u8 => deserialize_u8,
275        u16 => deserialize_u16,
276        u32 => deserialize_u32,
277        u64 => deserialize_u64,
278        i8 => deserialize_i8,
279        i16 => deserialize_i16,
280        i32 => deserialize_i32,
281        i64 => deserialize_i64,
282        u128 => deserialize_u128,
283        i128 => deserialize_i128,
284        f32 => deserialize_f32,
285        f64 => deserialize_f64,
286    }
287
288    fn deserialize_string<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
289        let result = match self.value() {
290            Value::String(s) => visitor.visit_str(s.expose()),
291            Value::Null => visitor.visit_string("null".to_string()),
292            Value::Bool(value) => visitor.visit_string(value.to_string()),
293            Value::Number(value) => visitor.visit_string(value.to_string()),
294            _ => Err(self.invalid_type("string or other primitive type")),
295        };
296        result.map_err(|err| err.set_origin_if_unset(&self.value.origin))
297    }
298
299    fn deserialize_char<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
300        self.deserialize_string(visitor)
301    }
302
303    fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
304        self.deserialize_string(visitor)
305    }
306
307    fn deserialize_byte_buf<V: de::Visitor<'de>>(
308        self,
309        visitor: V,
310    ) -> Result<V::Value, Self::Error> {
311        let result = match self.value() {
312            Value::String(s) => visitor.visit_str(s.expose()),
313            Value::Array(array) => self.parse_array(array, visitor),
314            _ => return Err(self.invalid_type("string or array")),
315        };
316        result.map_err(|err| err.set_origin_if_unset(&self.value.origin))
317    }
318
319    fn deserialize_bytes<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
320        self.deserialize_byte_buf(visitor)
321    }
322
323    fn deserialize_identifier<V: de::Visitor<'de>>(
324        self,
325        visitor: V,
326    ) -> Result<V::Value, Self::Error> {
327        self.deserialize_string(visitor)
328    }
329
330    fn deserialize_unit<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
331        let result = match self.value() {
332            Value::Null => visitor.visit_unit(),
333            _ => Err(self.invalid_type("null")),
334        };
335        result.map_err(|err| err.set_origin_if_unset(&self.value.origin))
336    }
337
338    fn deserialize_unit_struct<V: de::Visitor<'de>>(
339        self,
340        _name: &'static str,
341        visitor: V,
342    ) -> Result<V::Value, Self::Error> {
343        self.deserialize_unit(visitor)
344    }
345
346    fn deserialize_ignored_any<V: de::Visitor<'de>>(
347        self,
348        visitor: V,
349    ) -> Result<V::Value, Self::Error> {
350        visitor
351            .visit_unit()
352            .map_err(|err: serde_json::Error| self.enrich_err(err))
353    }
354}
355
356impl IntoDeserializer<'_, ErrorWithOrigin> for ValueDeserializer<'_> {
357    type Deserializer = Self;
358
359    fn into_deserializer(self) -> Self::Deserializer {
360        self
361    }
362}
363
364#[derive(Debug)]
365struct EnumDeserializer<'a> {
366    variant: &'a str,
367    inner: VariantDeserializer<'a>,
368}
369
370impl<'a, 'de> de::EnumAccess<'de> for EnumDeserializer<'a> {
371    type Error = ErrorWithOrigin;
372    type Variant = VariantDeserializer<'a>;
373
374    fn variant_seed<V: DeserializeSeed<'de>>(
375        self,
376        seed: V,
377    ) -> Result<(V::Value, Self::Variant), Self::Error> {
378        let variant = self.variant.into_deserializer();
379        match seed.deserialize(variant) {
380            Ok(val) => Ok((val, self.inner)),
381            Err(err) => Err(ErrorWithOrigin::json(err, self.inner.origin().clone())),
382        }
383    }
384}
385
386#[derive(Debug)]
387struct VariantDeserializer<'a> {
388    value: Option<&'a WithOrigin>,
389    options: &'a DeserializerOptions,
390    parent_origin: Arc<ValueOrigin>,
391}
392
393impl VariantDeserializer<'_> {
394    fn origin(&self) -> &Arc<ValueOrigin> {
395        self.value.map_or(&self.parent_origin, |val| &val.origin)
396    }
397}
398
399impl<'de> de::VariantAccess<'de> for VariantDeserializer<'_> {
400    type Error = ErrorWithOrigin;
401
402    fn unit_variant(self) -> Result<(), Self::Error> {
403        if let Some(value) = self.value {
404            Deserialize::deserialize(ValueDeserializer::new(value, self.options))
405        } else {
406            Ok(())
407        }
408    }
409
410    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
411    where
412        T: DeserializeSeed<'de>,
413    {
414        if let Some(value) = self.value {
415            seed.deserialize(ValueDeserializer::new(value, self.options))
416        } else {
417            let err = DeError::invalid_type(de::Unexpected::Unit, &"newtype variant");
418            Err(ErrorWithOrigin::json(err, self.parent_origin))
419        }
420    }
421
422    fn tuple_variant<V: de::Visitor<'de>>(
423        self,
424        _len: usize,
425        visitor: V,
426    ) -> Result<V::Value, Self::Error> {
427        if let Some(value) = self.value {
428            de::Deserializer::deserialize_seq(ValueDeserializer::new(value, self.options), visitor)
429        } else {
430            let err = DeError::invalid_type(de::Unexpected::Unit, &"tuple variant");
431            Err(ErrorWithOrigin::json(err, self.parent_origin))
432        }
433    }
434
435    fn struct_variant<V: de::Visitor<'de>>(
436        self,
437        _fields: &'static [&'static str],
438        visitor: V,
439    ) -> Result<V::Value, Self::Error> {
440        if let Some(value) = self.value {
441            de::Deserializer::deserialize_map(ValueDeserializer::new(value, self.options), visitor)
442        } else {
443            let err = DeError::invalid_type(de::Unexpected::Unit, &"struct variant");
444            Err(ErrorWithOrigin::json(err, self.parent_origin))
445        }
446    }
447}