Skip to main content

jasn_core/value/
de.rs

1//! Deserialization from JASN Value.
2//!
3//! This module provides deserialization from JASN `Value` to Rust types.
4
5use serde::de::{
6    self, Deserialize, DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, Visitor,
7};
8
9use crate::Value;
10
11/// Error type for deserialization.
12#[derive(Debug, thiserror::Error)]
13pub enum Error {
14    /// Custom deserialization error.
15    #[error("custom error: {0}")]
16    Custom(String),
17    /// Type mismatch during deserialization.
18    #[error("expected {expected}, got {got}")]
19    TypeMismatch {
20        /// Expected type.
21        expected: String,
22        /// Actual type.
23        got: String,
24    },
25    /// Invalid value encountered.
26    #[error("invalid value: {0}")]
27    InvalidValue(String),
28}
29
30impl de::Error for Error {
31    fn custom<T: std::fmt::Display>(msg: T) -> Self {
32        Error::Custom(msg.to_string())
33    }
34}
35
36type Result<T> = std::result::Result<T, Error>;
37
38/// Deserialize a JASN [`Value`] into a Rust value.
39pub fn from_value<'de, T>(value: &'de Value) -> Result<T>
40where
41    T: Deserialize<'de>,
42{
43    T::deserialize(Deserializer { value })
44}
45
46struct Deserializer<'de> {
47    value: &'de Value,
48}
49
50impl<'de> de::Deserializer<'de> for Deserializer<'de> {
51    type Error = Error;
52
53    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
54    where
55        V: Visitor<'de>,
56    {
57        match self.value {
58            Value::Null => visitor.visit_unit(),
59            Value::Bool(v) => visitor.visit_bool(*v),
60            Value::Int(v) => visitor.visit_i64(*v),
61            Value::Float(v) => visitor.visit_f64(*v),
62            Value::String(v) => visitor.visit_str(v),
63            Value::Binary(v) => visitor.visit_bytes(&v.0),
64            Value::Timestamp(_) => Err(Error::InvalidValue(
65                "timestamps must be deserialized explicitly".to_string(),
66            )),
67            Value::List(v) => visitor.visit_seq(SeqDeserializer { iter: v.iter() }),
68            Value::Map(v) => visitor.visit_map(MapDeserializer {
69                iter: v.iter(),
70                value: None,
71            }),
72        }
73    }
74
75    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
76    where
77        V: Visitor<'de>,
78    {
79        match self.value {
80            Value::Bool(v) => visitor.visit_bool(*v),
81            other => Err(Error::TypeMismatch {
82                expected: "bool".to_string(),
83                got: type_name(other),
84            }),
85        }
86    }
87
88    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
89    where
90        V: Visitor<'de>,
91    {
92        match self.value {
93            Value::Int(v) => visitor.visit_i8(*v as i8),
94            other => Err(Error::TypeMismatch {
95                expected: "i8".to_string(),
96                got: type_name(other),
97            }),
98        }
99    }
100
101    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
102    where
103        V: Visitor<'de>,
104    {
105        match self.value {
106            Value::Int(v) => visitor.visit_i16(*v as i16),
107            other => Err(Error::TypeMismatch {
108                expected: "i16".to_string(),
109                got: type_name(other),
110            }),
111        }
112    }
113
114    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
115    where
116        V: Visitor<'de>,
117    {
118        match self.value {
119            Value::Int(v) => visitor.visit_i32(*v as i32),
120            other => Err(Error::TypeMismatch {
121                expected: "i32".to_string(),
122                got: type_name(other),
123            }),
124        }
125    }
126
127    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
128    where
129        V: Visitor<'de>,
130    {
131        match self.value {
132            Value::Int(v) => visitor.visit_i64(*v),
133            other => Err(Error::TypeMismatch {
134                expected: "i64".to_string(),
135                got: type_name(other),
136            }),
137        }
138    }
139
140    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
141    where
142        V: Visitor<'de>,
143    {
144        match self.value {
145            Value::Int(v) => visitor.visit_u8(*v as u8),
146            other => Err(Error::TypeMismatch {
147                expected: "u8".to_string(),
148                got: type_name(other),
149            }),
150        }
151    }
152
153    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
154    where
155        V: Visitor<'de>,
156    {
157        match self.value {
158            Value::Int(v) => visitor.visit_u16(*v as u16),
159            other => Err(Error::TypeMismatch {
160                expected: "u16".to_string(),
161                got: type_name(other),
162            }),
163        }
164    }
165
166    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
167    where
168        V: Visitor<'de>,
169    {
170        match self.value {
171            Value::Int(v) => visitor.visit_u32(*v as u32),
172            other => Err(Error::TypeMismatch {
173                expected: "u32".to_string(),
174                got: type_name(other),
175            }),
176        }
177    }
178
179    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
180    where
181        V: Visitor<'de>,
182    {
183        match self.value {
184            Value::Int(v) => visitor.visit_u64(*v as u64),
185            other => Err(Error::TypeMismatch {
186                expected: "u64".to_string(),
187                got: type_name(other),
188            }),
189        }
190    }
191
192    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
193    where
194        V: Visitor<'de>,
195    {
196        match self.value {
197            Value::Float(v) => visitor.visit_f32(*v as f32),
198            Value::Int(v) => visitor.visit_f32(*v as f32),
199            other => Err(Error::TypeMismatch {
200                expected: "f32".to_string(),
201                got: type_name(other),
202            }),
203        }
204    }
205
206    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
207    where
208        V: Visitor<'de>,
209    {
210        match self.value {
211            Value::Float(v) => visitor.visit_f64(*v),
212            Value::Int(v) => visitor.visit_f64(*v as f64),
213            other => Err(Error::TypeMismatch {
214                expected: "f64".to_string(),
215                got: type_name(other),
216            }),
217        }
218    }
219
220    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
221    where
222        V: Visitor<'de>,
223    {
224        match self.value {
225            Value::String(v) => {
226                let mut chars = v.chars();
227                if let Some(ch) = chars.next()
228                    && chars.next().is_none()
229                {
230                    return visitor.visit_char(ch);
231                }
232
233                Err(Error::InvalidValue(format!(
234                    "expected single character, got: {}",
235                    v
236                )))
237            }
238            other => Err(Error::TypeMismatch {
239                expected: "char".to_string(),
240                got: type_name(other),
241            }),
242        }
243    }
244
245    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
246    where
247        V: Visitor<'de>,
248    {
249        match self.value {
250            Value::String(v) => visitor.visit_str(v),
251            other => Err(Error::TypeMismatch {
252                expected: "string".to_string(),
253                got: type_name(other),
254            }),
255        }
256    }
257
258    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
259    where
260        V: Visitor<'de>,
261    {
262        self.deserialize_str(visitor)
263    }
264
265    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
266    where
267        V: Visitor<'de>,
268    {
269        match self.value {
270            Value::Binary(v) => visitor.visit_bytes(&v.0),
271            other => Err(Error::TypeMismatch {
272                expected: "bytes".to_string(),
273                got: type_name(other),
274            }),
275        }
276    }
277
278    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
279    where
280        V: Visitor<'de>,
281    {
282        self.deserialize_bytes(visitor)
283    }
284
285    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
286    where
287        V: Visitor<'de>,
288    {
289        match self.value {
290            Value::Null => visitor.visit_none(),
291            _ => visitor.visit_some(self),
292        }
293    }
294
295    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
296    where
297        V: Visitor<'de>,
298    {
299        match self.value {
300            Value::Null => visitor.visit_unit(),
301            other => Err(Error::TypeMismatch {
302                expected: "null".to_string(),
303                got: type_name(other),
304            }),
305        }
306    }
307
308    fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
309    where
310        V: Visitor<'de>,
311    {
312        self.deserialize_unit(visitor)
313    }
314
315    fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
316    where
317        V: Visitor<'de>,
318    {
319        visitor.visit_newtype_struct(self)
320    }
321
322    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
323    where
324        V: Visitor<'de>,
325    {
326        match self.value {
327            Value::List(v) => visitor.visit_seq(SeqDeserializer { iter: v.iter() }),
328            other => Err(Error::TypeMismatch {
329                expected: "array".to_string(),
330                got: type_name(other),
331            }),
332        }
333    }
334
335    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
336    where
337        V: Visitor<'de>,
338    {
339        self.deserialize_seq(visitor)
340    }
341
342    fn deserialize_tuple_struct<V>(
343        self,
344        _name: &'static str,
345        _len: usize,
346        visitor: V,
347    ) -> Result<V::Value>
348    where
349        V: Visitor<'de>,
350    {
351        self.deserialize_seq(visitor)
352    }
353
354    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
355    where
356        V: Visitor<'de>,
357    {
358        match self.value {
359            Value::Map(v) => visitor.visit_map(MapDeserializer {
360                iter: v.iter(),
361                value: None,
362            }),
363            other => Err(Error::TypeMismatch {
364                expected: "map".to_string(),
365                got: type_name(other),
366            }),
367        }
368    }
369
370    fn deserialize_struct<V>(
371        self,
372        _name: &'static str,
373        _fields: &'static [&'static str],
374        visitor: V,
375    ) -> Result<V::Value>
376    where
377        V: Visitor<'de>,
378    {
379        self.deserialize_map(visitor)
380    }
381
382    fn deserialize_enum<V>(
383        self,
384        _name: &'static str,
385        _variants: &'static [&'static str],
386        visitor: V,
387    ) -> Result<V::Value>
388    where
389        V: Visitor<'de>,
390    {
391        match self.value {
392            Value::String(s) => visitor.visit_enum(s.as_str().into_deserializer()),
393            Value::Map(m) => {
394                if m.len() == 1 {
395                    let (key, value) = m.iter().next().unwrap();
396                    visitor.visit_enum(EnumDeserializer { key, value })
397                } else {
398                    Err(Error::InvalidValue(
399                        "enum must be a string or single-key map".to_string(),
400                    ))
401                }
402            }
403            other => Err(Error::TypeMismatch {
404                expected: "enum".to_string(),
405                got: type_name(other),
406            }),
407        }
408    }
409
410    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
411    where
412        V: Visitor<'de>,
413    {
414        self.deserialize_str(visitor)
415    }
416
417    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
418    where
419        V: Visitor<'de>,
420    {
421        visitor.visit_unit()
422    }
423}
424
425struct SeqDeserializer<'de> {
426    iter: std::slice::Iter<'de, Value>,
427}
428
429impl<'de> SeqAccess<'de> for SeqDeserializer<'de> {
430    type Error = Error;
431
432    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
433    where
434        T: DeserializeSeed<'de>,
435    {
436        match self.iter.next() {
437            Some(value) => seed.deserialize(Deserializer { value }).map(Some),
438            None => Ok(None),
439        }
440    }
441}
442
443struct MapDeserializer<'de> {
444    iter: std::collections::btree_map::Iter<'de, String, Value>,
445    value: Option<&'de Value>,
446}
447
448impl<'de> MapAccess<'de> for MapDeserializer<'de> {
449    type Error = Error;
450
451    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
452    where
453        K: DeserializeSeed<'de>,
454    {
455        match self.iter.next() {
456            Some((key, value)) => {
457                self.value = Some(value);
458                seed.deserialize(key.as_str().into_deserializer()).map(Some)
459            }
460            None => Ok(None),
461        }
462    }
463
464    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
465    where
466        V: DeserializeSeed<'de>,
467    {
468        match self.value.take() {
469            Some(value) => seed.deserialize(Deserializer { value }),
470            None => Err(Error::Custom("value is missing".to_string())),
471        }
472    }
473}
474
475struct EnumDeserializer<'de> {
476    key: &'de String,
477    value: &'de Value,
478}
479
480impl<'de> de::EnumAccess<'de> for EnumDeserializer<'de> {
481    type Error = Error;
482    type Variant = VariantDeserializer<'de>;
483
484    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
485    where
486        V: DeserializeSeed<'de>,
487    {
488        use serde::de::value::StrDeserializer;
489        let deserializer: StrDeserializer<Error> = self.key.as_str().into_deserializer();
490        let variant = seed.deserialize(deserializer)?;
491        Ok((variant, VariantDeserializer { value: self.value }))
492    }
493}
494
495struct VariantDeserializer<'de> {
496    value: &'de Value,
497}
498
499impl<'de> de::VariantAccess<'de> for VariantDeserializer<'de> {
500    type Error = Error;
501
502    fn unit_variant(self) -> Result<()> {
503        Ok(())
504    }
505
506    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
507    where
508        T: DeserializeSeed<'de>,
509    {
510        seed.deserialize(Deserializer { value: self.value })
511    }
512
513    fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
514    where
515        V: Visitor<'de>,
516    {
517        match self.value {
518            Value::List(v) => visitor.visit_seq(SeqDeserializer { iter: v.iter() }),
519            other => Err(Error::TypeMismatch {
520                expected: "array for tuple variant".to_string(),
521                got: type_name(other),
522            }),
523        }
524    }
525
526    fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
527    where
528        V: Visitor<'de>,
529    {
530        match self.value {
531            Value::Map(v) => visitor.visit_map(MapDeserializer {
532                iter: v.iter(),
533                value: None,
534            }),
535            other => Err(Error::TypeMismatch {
536                expected: "map for struct variant".to_string(),
537                got: type_name(other),
538            }),
539        }
540    }
541}
542
543fn type_name(value: &Value) -> String {
544    match value {
545        Value::Null => "null",
546        Value::Bool(_) => "bool",
547        Value::Int(_) => "int",
548        Value::Float(_) => "float",
549        Value::String(_) => "string",
550        Value::Binary(_) => "binary",
551        Value::Timestamp(_) => "timestamp",
552        Value::List(_) => "lists",
553        Value::Map(_) => "map",
554    }
555    .to_string()
556}