Skip to main content

nested_text/
de.rs

1use crate::error::{Error, ErrorKind};
2use crate::parser::{loads, Top};
3use crate::value::Value;
4
5use serde::de::{self, DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, Visitor};
6use serde::Deserialize;
7
8/// Deserialize a NestedText string into a type that implements Deserialize.
9///
10/// Since NestedText only has string scalars, numeric/boolean fields are parsed
11/// from their string representation.
12pub fn from_str<'de, T: Deserialize<'de>>(s: &'de str) -> Result<T, Error> {
13    let value = loads(s, Top::Any)?.unwrap_or(Value::String(String::new()));
14    T::deserialize(ValueDeserializer { value: &value })
15}
16
17struct ValueDeserializer<'a> {
18    value: &'a Value,
19}
20
21impl<'de, 'a> de::Deserializer<'de> for ValueDeserializer<'a> {
22    type Error = Error;
23
24    fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
25        match self.value {
26            Value::String(s) => visitor.visit_str(s),
27            Value::List(_) => self.deserialize_seq(visitor),
28            Value::Dict(_) => self.deserialize_map(visitor),
29        }
30    }
31
32    fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
33        match self.value {
34            Value::String(s) => match s.as_str() {
35                "true" | "True" | "TRUE" | "yes" | "Yes" | "YES" => visitor.visit_bool(true),
36                "false" | "False" | "FALSE" | "no" | "No" | "NO" => visitor.visit_bool(false),
37                _ => Err(Error::new(
38                    ErrorKind::UnsupportedType,
39                    format!("cannot parse '{}' as boolean", s),
40                )),
41            },
42            _ => Err(Error::new(
43                ErrorKind::UnsupportedType,
44                "expected string for boolean",
45            )),
46        }
47    }
48
49    fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
50        let s = self.expect_string()?;
51        let n: i8 = s.parse().map_err(|_| {
52            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as i8", s))
53        })?;
54        visitor.visit_i8(n)
55    }
56
57    fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
58        let s = self.expect_string()?;
59        let n: i16 = s.parse().map_err(|_| {
60            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as i16", s))
61        })?;
62        visitor.visit_i16(n)
63    }
64
65    fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
66        let s = self.expect_string()?;
67        let n: i32 = s.parse().map_err(|_| {
68            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as i32", s))
69        })?;
70        visitor.visit_i32(n)
71    }
72
73    fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
74        let s = self.expect_string()?;
75        let n: i64 = s.parse().map_err(|_| {
76            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as i64", s))
77        })?;
78        visitor.visit_i64(n)
79    }
80
81    fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
82        let s = self.expect_string()?;
83        let n: u8 = s.parse().map_err(|_| {
84            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as u8", s))
85        })?;
86        visitor.visit_u8(n)
87    }
88
89    fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
90        let s = self.expect_string()?;
91        let n: u16 = s.parse().map_err(|_| {
92            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as u16", s))
93        })?;
94        visitor.visit_u16(n)
95    }
96
97    fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
98        let s = self.expect_string()?;
99        let n: u32 = s.parse().map_err(|_| {
100            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as u32", s))
101        })?;
102        visitor.visit_u32(n)
103    }
104
105    fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
106        let s = self.expect_string()?;
107        let n: u64 = s.parse().map_err(|_| {
108            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as u64", s))
109        })?;
110        visitor.visit_u64(n)
111    }
112
113    fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
114        let s = self.expect_string()?;
115        let n: f32 = s.parse().map_err(|_| {
116            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as f32", s))
117        })?;
118        visitor.visit_f32(n)
119    }
120
121    fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
122        let s = self.expect_string()?;
123        let n: f64 = s.parse().map_err(|_| {
124            Error::new(ErrorKind::UnsupportedType, format!("cannot parse '{}' as f64", s))
125        })?;
126        visitor.visit_f64(n)
127    }
128
129    fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
130        let s = self.expect_string()?;
131        let mut chars = s.chars();
132        let c = chars.next().ok_or_else(|| {
133            Error::new(ErrorKind::UnsupportedType, "empty string for char")
134        })?;
135        if chars.next().is_some() {
136            return Err(Error::new(
137                ErrorKind::UnsupportedType,
138                "expected single character",
139            ));
140        }
141        visitor.visit_char(c)
142    }
143
144    fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
145        let s = self.expect_string()?;
146        visitor.visit_str(s)
147    }
148
149    fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
150        let s = self.expect_string()?;
151        visitor.visit_string(s.to_string())
152    }
153
154    fn deserialize_bytes<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Error> {
155        Err(Error::new(
156            ErrorKind::UnsupportedType,
157            "NestedText does not support byte arrays",
158        ))
159    }
160
161    fn deserialize_byte_buf<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Error> {
162        Err(Error::new(
163            ErrorKind::UnsupportedType,
164            "NestedText does not support byte arrays",
165        ))
166    }
167
168    fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
169        // Empty string = None, anything else = Some
170        match self.value {
171            Value::String(s) if s.is_empty() => visitor.visit_none(),
172            _ => visitor.visit_some(self),
173        }
174    }
175
176    fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
177        match self.value {
178            Value::String(s) if s.is_empty() => visitor.visit_unit(),
179            _ => Err(Error::new(
180                ErrorKind::UnsupportedType,
181                "expected empty string for unit",
182            )),
183        }
184    }
185
186    fn deserialize_unit_struct<V: Visitor<'de>>(
187        self,
188        _name: &'static str,
189        visitor: V,
190    ) -> Result<V::Value, Error> {
191        self.deserialize_unit(visitor)
192    }
193
194    fn deserialize_newtype_struct<V: Visitor<'de>>(
195        self,
196        _name: &'static str,
197        visitor: V,
198    ) -> Result<V::Value, Error> {
199        visitor.visit_newtype_struct(self)
200    }
201
202    fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
203        match self.value {
204            Value::List(items) => visitor.visit_seq(SeqDeserializer {
205                iter: items.iter(),
206            }),
207            _ => Err(Error::new(
208                ErrorKind::UnsupportedType,
209                "expected list for sequence",
210            )),
211        }
212    }
213
214    fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value, Error> {
215        self.deserialize_seq(visitor)
216    }
217
218    fn deserialize_tuple_struct<V: Visitor<'de>>(
219        self,
220        _name: &'static str,
221        _len: usize,
222        visitor: V,
223    ) -> Result<V::Value, Error> {
224        self.deserialize_seq(visitor)
225    }
226
227    fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
228        match self.value {
229            Value::Dict(pairs) => visitor.visit_map(MapDeserializer {
230                iter: pairs.iter(),
231                next_value: None,
232            }),
233            _ => Err(Error::new(
234                ErrorKind::UnsupportedType,
235                "expected dictionary for map",
236            )),
237        }
238    }
239
240    fn deserialize_struct<V: Visitor<'de>>(
241        self,
242        _name: &'static str,
243        _fields: &'static [&'static str],
244        visitor: V,
245    ) -> Result<V::Value, Error> {
246        self.deserialize_map(visitor)
247    }
248
249    fn deserialize_enum<V: Visitor<'de>>(
250        self,
251        _name: &'static str,
252        _variants: &'static [&'static str],
253        visitor: V,
254    ) -> Result<V::Value, Error> {
255        match self.value {
256            // Unit variant: just a string
257            Value::String(s) => visitor.visit_enum(s.as_str().into_deserializer()),
258            // Other variants: dict with single key = variant name
259            Value::Dict(pairs) => {
260                if pairs.len() != 1 {
261                    return Err(Error::new(
262                        ErrorKind::UnsupportedType,
263                        "enum must be a string or single-key dictionary",
264                    ));
265                }
266                let (variant, value) = &pairs[0];
267                visitor.visit_enum(EnumDeserializer {
268                    variant,
269                    value,
270                })
271            }
272            _ => Err(Error::new(
273                ErrorKind::UnsupportedType,
274                "expected string or dictionary for enum",
275            )),
276        }
277    }
278
279    fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
280        self.deserialize_str(visitor)
281    }
282
283    fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
284        self.deserialize_any(visitor)
285    }
286}
287
288impl<'a> ValueDeserializer<'a> {
289    fn expect_string(&self) -> Result<&'a str, Error> {
290        match self.value {
291            Value::String(s) => Ok(s.as_str()),
292            _ => Err(Error::new(
293                ErrorKind::UnsupportedType,
294                "expected string value",
295            )),
296        }
297    }
298}
299
300// Sequence deserializer
301struct SeqDeserializer<'a> {
302    iter: std::slice::Iter<'a, Value>,
303}
304
305impl<'de, 'a> SeqAccess<'de> for SeqDeserializer<'a> {
306    type Error = Error;
307
308    fn next_element_seed<T: DeserializeSeed<'de>>(
309        &mut self,
310        seed: T,
311    ) -> Result<Option<T::Value>, Error> {
312        match self.iter.next() {
313            Some(value) => seed
314                .deserialize(ValueDeserializer { value })
315                .map(Some),
316            None => Ok(None),
317        }
318    }
319}
320
321// Map deserializer
322struct MapDeserializer<'a> {
323    iter: std::slice::Iter<'a, (String, Value)>,
324    next_value: Option<&'a Value>,
325}
326
327impl<'de, 'a> MapAccess<'de> for MapDeserializer<'a> {
328    type Error = Error;
329
330    fn next_key_seed<K: DeserializeSeed<'de>>(
331        &mut self,
332        seed: K,
333    ) -> Result<Option<K::Value>, Error> {
334        match self.iter.next() {
335            Some((key, value)) => {
336                self.next_value = Some(value);
337                let key_value = Value::String(key.clone());
338                seed.deserialize(ValueDeserializer { value: &key_value })
339                    .map(Some)
340            }
341            None => Ok(None),
342        }
343    }
344
345    fn next_value_seed<V: DeserializeSeed<'de>>(
346        &mut self,
347        seed: V,
348    ) -> Result<V::Value, Error> {
349        let value = self.next_value.take().expect("next_value called before next_key");
350        seed.deserialize(ValueDeserializer { value })
351    }
352}
353
354// Enum deserializer
355struct EnumDeserializer<'a> {
356    variant: &'a str,
357    value: &'a Value,
358}
359
360impl<'de, 'a> de::EnumAccess<'de> for EnumDeserializer<'a> {
361    type Error = Error;
362    type Variant = VariantDeserializer<'a>;
363
364    fn variant_seed<V: DeserializeSeed<'de>>(
365        self,
366        seed: V,
367    ) -> Result<(V::Value, Self::Variant), Error> {
368        let variant_value = Value::String(self.variant.to_string());
369        let v = seed.deserialize(ValueDeserializer {
370            value: &variant_value,
371        })?;
372        Ok((v, VariantDeserializer { value: self.value }))
373    }
374}
375
376struct VariantDeserializer<'a> {
377    value: &'a Value,
378}
379
380impl<'de, 'a> de::VariantAccess<'de> for VariantDeserializer<'a> {
381    type Error = Error;
382
383    fn unit_variant(self) -> Result<(), Error> {
384        Ok(())
385    }
386
387    fn newtype_variant_seed<T: DeserializeSeed<'de>>(
388        self,
389        seed: T,
390    ) -> Result<T::Value, Error> {
391        seed.deserialize(ValueDeserializer { value: self.value })
392    }
393
394    fn tuple_variant<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value, Error> {
395        match self.value {
396            Value::List(items) => visitor.visit_seq(SeqDeserializer {
397                iter: items.iter(),
398            }),
399            _ => Err(Error::new(
400                ErrorKind::UnsupportedType,
401                "expected list for tuple variant",
402            )),
403        }
404    }
405
406    fn struct_variant<V: Visitor<'de>>(
407        self,
408        _fields: &'static [&'static str],
409        visitor: V,
410    ) -> Result<V::Value, Error> {
411        match self.value {
412            Value::Dict(pairs) => visitor.visit_map(MapDeserializer {
413                iter: pairs.iter(),
414                next_value: None,
415            }),
416            _ => Err(Error::new(
417                ErrorKind::UnsupportedType,
418                "expected dictionary for struct variant",
419            )),
420        }
421    }
422}
423
424// Make Error work with serde
425impl de::Error for Error {
426    fn custom<T: std::fmt::Display>(msg: T) -> Self {
427        Error::new(ErrorKind::UnsupportedType, msg.to_string())
428    }
429}
430
431#[cfg(test)]
432mod tests {
433    use super::*;
434    use serde::Deserialize;
435
436    #[test]
437    fn test_deserialize_struct() {
438        #[derive(Deserialize, Debug, PartialEq)]
439        struct Config {
440            name: String,
441            age: u32,
442        }
443        let input = "name: Alice\nage: 30";
444        let config: Config = from_str(input).unwrap();
445        assert_eq!(
446            config,
447            Config {
448                name: "Alice".to_string(),
449                age: 30,
450            }
451        );
452    }
453
454    #[test]
455    fn test_deserialize_vec() {
456        let input = "- hello\n- world";
457        let v: Vec<String> = from_str(input).unwrap();
458        assert_eq!(v, vec!["hello", "world"]);
459    }
460
461    #[test]
462    fn test_deserialize_nested() {
463        #[derive(Deserialize, Debug, PartialEq)]
464        struct Outer {
465            items: Vec<String>,
466        }
467        let input = "items:\n  - a\n  - b";
468        let v: Outer = from_str(input).unwrap();
469        assert_eq!(
470            v,
471            Outer {
472                items: vec!["a".to_string(), "b".to_string()],
473            }
474        );
475    }
476
477    #[test]
478    fn test_deserialize_bool() {
479        #[derive(Deserialize, Debug, PartialEq)]
480        struct Flags {
481            debug: bool,
482            verbose: bool,
483        }
484        let input = "debug: true\nverbose: false";
485        let v: Flags = from_str(input).unwrap();
486        assert_eq!(
487            v,
488            Flags {
489                debug: true,
490                verbose: false,
491            }
492        );
493    }
494
495    #[test]
496    fn test_deserialize_option() {
497        #[derive(Deserialize, Debug, PartialEq)]
498        struct MaybeValue {
499            present: Option<String>,
500            absent: Option<String>,
501        }
502        let input = "present: hello\nabsent:";
503        let v: MaybeValue = from_str(input).unwrap();
504        assert_eq!(
505            v,
506            MaybeValue {
507                present: Some("hello".to_string()),
508                absent: None,
509            }
510        );
511    }
512
513    #[test]
514    fn test_deserialize_enum() {
515        #[derive(Deserialize, Debug, PartialEq)]
516        enum Color {
517            Red,
518            Green,
519            Blue,
520        }
521        let input = "> Red";
522        let v: Color = from_str(input).unwrap();
523        assert_eq!(v, Color::Red);
524    }
525
526    #[test]
527    fn test_deserialize_hashmap() {
528        use std::collections::HashMap;
529        let input = "a: 1\nb: 2";
530        let v: HashMap<String, String> = from_str(input).unwrap();
531        assert_eq!(v.get("a").unwrap(), "1");
532        assert_eq!(v.get("b").unwrap(), "2");
533    }
534}