hocon_linked/serde/
de.rs

1//! Deserializer methods using serde
2
3use super::error::{Error, Result};
4use crate::Hocon;
5
6pub use super::wrappers;
7
8macro_rules! impl_deserialize_n {
9    ($method:ident, $visit:ident) => {
10        fn $method<V>(self, visitor: V) -> Result<V::Value>
11        where
12            V: serde::de::Visitor<'de>,
13        {
14            visitor.$visit(
15                self.read
16                    .get_attribute_value(&self.current_field)
17                    .ok_or_else(|| Error {
18                        message: format!("missing integer for field \"{}\"", self.current_field),
19                    })?
20                    .clone()
21                    .as_i64()
22                    .ok_or_else(|| Error {
23                        message: format!(
24                            "Invalid type for field \"{}\", expected integer",
25                            self.current_field
26                        ),
27                    })?,
28            )
29        }
30    };
31    ($type:ty, $method:ident, $visit:ident) => {
32        fn $method<V>(self, visitor: V) -> Result<V::Value>
33        where
34            V: serde::de::Visitor<'de>,
35        {
36            visitor.$visit(
37                self.read
38                    .get_attribute_value(&self.current_field)
39                    .ok_or_else(|| Error {
40                        message: format!("missing integer for field \"{}\"", self.current_field),
41                    })?
42                    .clone()
43                    .as_i64()
44                    .ok_or_else(|| Error {
45                        message: format!(
46                            "Invalid type for field \"{}\", expected integer",
47                            self.current_field
48                        ),
49                    })? as $type,
50            )
51        }
52    };
53}
54macro_rules! impl_deserialize_f {
55    ($method:ident, $visit:ident) => {
56        fn $method<V>(self, visitor: V) -> Result<V::Value>
57        where
58            V: serde::de::Visitor<'de>,
59        {
60            visitor.$visit(
61                self.read
62                    .get_attribute_value(&self.current_field)
63                    .ok_or_else(|| Error {
64                        message: format!("missing float for field \"{}\"", self.current_field),
65                    })?
66                    .clone()
67                    .as_f64()
68                    .ok_or_else(|| Error {
69                        message: format!(
70                            "Invalid type for field \"{}\", expected float",
71                            self.current_field
72                        ),
73                    })?,
74            )
75        }
76    };
77    ($type:ty, $method:ident, $visit:ident) => {
78        fn $method<V>(self, visitor: V) -> Result<V::Value>
79        where
80            V: serde::de::Visitor<'de>,
81        {
82            visitor.$visit(
83                self.read
84                    .get_attribute_value(&self.current_field)
85                    .ok_or_else(|| Error {
86                        message: format!("missing float for field \"{}\"", self.current_field),
87                    })?
88                    .clone()
89                    .as_f64()
90                    .ok_or_else(|| Error {
91                        message: format!(
92                            "Invalid type for field \"{}\", expected float",
93                            self.current_field
94                        ),
95                    })? as $type,
96            )
97        }
98    };
99}
100
101#[derive(Debug)]
102enum Index {
103    String(String),
104    Number(usize),
105    None,
106}
107
108impl std::fmt::Display for Index {
109    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
110        match self {
111            Index::String(field) => write!(f, "{}", field),
112            Index::Number(field) => write!(f, "{}", field),
113            Index::None => write!(f, ""),
114        }
115    }
116}
117
118trait Read {
119    fn get_attribute_value(&self, index: &Index) -> Option<&Hocon>;
120    fn get_keys(&self) -> Vec<String>;
121}
122
123struct HoconRead {
124    hocon: Hocon,
125}
126impl HoconRead {
127    fn new(hocon: Hocon) -> Self {
128        HoconRead { hocon }
129    }
130}
131impl Read for HoconRead {
132    fn get_attribute_value(&self, index: &Index) -> Option<&Hocon> {
133        match *index {
134            Index::String(ref key) => match &self.hocon[key.as_ref()] {
135                Hocon::BadValue(_) => None,
136                v => Some(v),
137            },
138            Index::Number(key) => match &self.hocon[key] {
139                Hocon::BadValue(_) => None,
140                v => Some(v),
141            },
142            _ => None,
143        }
144    }
145
146    fn get_keys(&self) -> Vec<String> {
147        match &self.hocon {
148            Hocon::Hash(map) => map.keys().cloned().collect(),
149            _ => unreachable!(),
150        }
151    }
152}
153
154#[derive(Debug)]
155struct Deserializer<R> {
156    read: R,
157    current_field: Index,
158    as_key: bool,
159}
160impl<'de, R> Deserializer<R>
161where
162    R: Read,
163{
164    pub fn new(read: R) -> Self {
165        Deserializer {
166            read,
167            current_field: Index::None,
168            as_key: false,
169        }
170    }
171}
172
173impl<'de, 'a, R: Read> serde::de::Deserializer<'de> for &'a mut Deserializer<R> {
174    type Error = Error;
175
176    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
177    where
178        V: serde::de::Visitor<'de>,
179    {
180        if self.as_key {
181            self.deserialize_identifier(visitor)
182        } else {
183            let f: Hocon = self
184                .read
185                .get_attribute_value(&self.current_field)
186                .ok_or_else(|| Error {
187                    message: format!("missing value for field \"{}\"", self.current_field),
188                })?
189                .clone();
190            match f {
191                Hocon::Boolean(_) => self.deserialize_bool(visitor),
192                Hocon::Real(_) => self.deserialize_f64(visitor),
193                Hocon::Integer(_) => self.deserialize_i64(visitor),
194                Hocon::String(_) => self.deserialize_string(visitor),
195                Hocon::Array(_) => self.deserialize_seq(visitor),
196                Hocon::Hash(_) => self.deserialize_map(visitor),
197                Hocon::Null => self.deserialize_option(visitor),
198                Hocon::BadValue(err) => Err(Error {
199                    message: format!("error for field \"{}\": {}", self.current_field, err),
200                }),
201            }
202        }
203    }
204
205    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
206    where
207        V: serde::de::Visitor<'de>,
208    {
209        visitor.visit_bool(
210            self.read
211                .get_attribute_value(&self.current_field)
212                .ok_or_else(|| Error {
213                    message: format!("Missing field \"{}\"", self.current_field),
214                })?
215                .clone()
216                .as_bool()
217                .ok_or_else(|| Error {
218                    message: format!(
219                        "Invalid type for field \"{}\", expected bool",
220                        self.current_field
221                    ),
222                })?,
223        )
224    }
225
226    impl_deserialize_n!(i8, deserialize_i8, visit_i8);
227    impl_deserialize_n!(i16, deserialize_i16, visit_i16);
228    impl_deserialize_n!(i32, deserialize_i32, visit_i32);
229    impl_deserialize_n!(deserialize_i64, visit_i64);
230    // impl_deserialize_n!(i64, deserialize_i64, visit_i64);
231
232    impl_deserialize_n!(u8, deserialize_u8, visit_u8);
233    impl_deserialize_n!(u16, deserialize_u16, visit_u16);
234    impl_deserialize_n!(u32, deserialize_u32, visit_u32);
235    impl_deserialize_n!(u64, deserialize_u64, visit_u64);
236
237    impl_deserialize_f!(f32, deserialize_f32, visit_f32);
238    impl_deserialize_f!(deserialize_f64, visit_f64);
239    // impl_deserialize_f!(f64, deserialize_f64, visit_f64);
240
241    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
242    where
243        V: serde::de::Visitor<'de>,
244    {
245        visitor.visit_char(
246            self.read
247                .get_attribute_value(&self.current_field)
248                .ok_or_else(|| Error {
249                    message: format!("missing char for field \"{}\"", self.current_field),
250                })?
251                .clone()
252                .as_string()
253                .ok_or_else(|| Error {
254                    message: format!("missing char for field \"{}\"", self.current_field),
255                })?
256                .parse::<char>()
257                .map_err(|_| Error {
258                    message: format!("Expected char type for field \"{}\"", self.current_field),
259                })?,
260        )
261    }
262
263    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
264    where
265        V: serde::de::Visitor<'de>,
266    {
267        if self.as_key {
268            match &self.current_field {
269                Index::String(ref key) => visitor.visit_str(key),
270                _ => visitor.visit_str(""),
271            }
272        } else if let Some(field) = self.read.get_attribute_value(&self.current_field) {
273            field
274                .clone()
275                .as_string()
276                .ok_or_else(|| Error {
277                    message: format!("missing string for field \"{}\"", self.current_field),
278                })
279                .and_then(|string_field| visitor.visit_str(&string_field))
280        } else {
281            visitor.visit_str("")
282        }
283    }
284
285    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
286    where
287        V: serde::de::Visitor<'de>,
288    {
289        self.deserialize_str(visitor)
290    }
291
292    fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
293    where
294        V: serde::de::Visitor<'de>,
295    {
296        unimplemented!()
297    }
298
299    fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value>
300    where
301        V: serde::de::Visitor<'de>,
302    {
303        unimplemented!()
304    }
305
306    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
307    where
308        V: serde::de::Visitor<'de>,
309    {
310        if self.read.get_attribute_value(&self.current_field).is_none() {
311            return visitor.visit_none();
312        }
313        match self
314            .read
315            .get_attribute_value(&self.current_field)
316            .ok_or_else(|| Error {
317                message: format!("missing option for field \"{}\"", self.current_field),
318            })? {
319            Hocon::Null => visitor.visit_none(),
320            _ => visitor.visit_some(self),
321        }
322    }
323
324    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
325    where
326        V: serde::de::Visitor<'de>,
327    {
328        match self
329            .read
330            .get_attribute_value(&self.current_field)
331            .ok_or_else(|| Error {
332                message: format!("missing option for field \"{}\"", self.current_field),
333            })? {
334            Hocon::Null => visitor.visit_unit(),
335            _ => visitor.visit_unit(),
336        }
337    }
338
339    fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
340    where
341        V: serde::de::Visitor<'de>,
342    {
343        self.deserialize_unit(visitor)
344    }
345
346    fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value>
347    where
348        V: serde::de::Visitor<'de>,
349    {
350        visitor.visit_newtype_struct(self)
351    }
352
353    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
354    where
355        V: serde::de::Visitor<'de>,
356    {
357        let list = self
358            .read
359            .get_attribute_value(&self.current_field)
360            .ok_or_else(|| Error {
361                message: format!("missing sequence for field \"{}\"", self.current_field),
362            })?
363            .clone();
364        let read = match list {
365            Hocon::Array(_) | Hocon::Hash(_) => HoconRead { hocon: list },
366            _ => {
367                return Err(Error {
368                    message: format!(
369                        "No sequence input found for field \"{}\"",
370                        self.current_field
371                    ),
372                });
373            }
374        };
375        let mut des = Deserializer::new(read);
376        visitor.visit_seq(SeqAccess::new(&mut des))
377    }
378
379    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
380    where
381        V: serde::de::Visitor<'de>,
382    {
383        let list = self
384            .read
385            .get_attribute_value(&self.current_field)
386            .ok_or_else(|| Error {
387                message: format!("missing sequence for field \"{}\"", &self.current_field),
388            })?
389            .clone();
390        let read = match list {
391            Hocon::Array(_) | Hocon::Hash(_) => HoconRead { hocon: list },
392            _ => {
393                return Err(Error {
394                    message: format!(
395                        "No sequence input found for field \"{}\"",
396                        self.current_field
397                    ),
398                });
399            }
400        };
401        let mut des = Deserializer::new(read);
402        visitor.visit_seq(SeqAccess::new(&mut des))
403    }
404
405    fn deserialize_tuple_struct<V>(
406        self,
407        _name: &'static str,
408        len: usize,
409        visitor: V,
410    ) -> Result<V::Value>
411    where
412        V: serde::de::Visitor<'de>,
413    {
414        self.deserialize_tuple(len, visitor)
415    }
416
417    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
418    where
419        V: serde::de::Visitor<'de>,
420    {
421        match self.current_field {
422            Index::None => visitor.visit_map(MapAccess::new(self, self.read.get_keys())),
423            _ => {
424                let hc = self
425                    .read
426                    .get_attribute_value(&self.current_field)
427                    .ok_or_else(|| Error {
428                        message: format!("missing struct for field \"{}\"", self.current_field),
429                    })?
430                    .clone();
431                let keys = match &hc {
432                    Hocon::Hash(hm) => hm.keys().cloned().collect(),
433                    _ => {
434                        return Err(Error {
435                            message: format!("invalid type for field \"{}\"", self.current_field),
436                        })
437                    }
438                };
439                let mut des = Deserializer::new(HoconRead::new(hc));
440                visitor.visit_map(MapAccess::new(&mut des, keys))
441            }
442        }
443    }
444
445    fn deserialize_struct<V>(
446        self,
447        _name: &'static str,
448        _fields: &'static [&'static str],
449        visitor: V,
450    ) -> Result<V::Value>
451    where
452        V: serde::de::Visitor<'de>,
453    {
454        self.deserialize_map(visitor)
455    }
456
457    fn deserialize_enum<V>(
458        self,
459        _name: &str,
460        variants: &'static [&'static str],
461        visitor: V,
462    ) -> Result<V::Value>
463    where
464        V: serde::de::Visitor<'de>,
465    {
466        let hc = self
467            .read
468            .get_attribute_value(&self.current_field)
469            .ok_or_else(|| Error {
470                message: format!("missing struct for field \"{}\"", self.current_field),
471            })?
472            .clone();
473
474        if let Index::String(ref s) = self.current_field {
475            for v in variants {
476                if s == v {
477                    let reader = HoconRead::new(hc);
478                    let deserializer = &mut Deserializer::new(reader);
479                    deserializer.current_field = Index::String(String::from(s));
480                    return visitor.visit_enum(UnitVariantAccess::new(deserializer));
481                }
482            }
483        }
484
485        match &hc {
486            Hocon::String(name) => {
487                let index = Index::String(String::from(name));
488                let reader = HoconRead::new(hc);
489                let deserializer = &mut Deserializer::new(reader);
490                deserializer.current_field = index;
491                visitor.visit_enum(UnitVariantAccess::new(deserializer))
492            }
493            Hocon::Hash(variant_map) => {
494                let mut keys = variant_map.keys();
495                let first_key = keys.next().ok_or_else(|| Error {
496                    message: format!(
497                        "non unit enum variant should have enum serialized for field \"{}\"",
498                        self.current_field
499                    ),
500                })?;
501                if let Some(_other_key) = keys.next() {
502                    return Err(Error {
503                        message: format!(
504                            "non unit enum variant should have enum serialized for field \"{}\"",
505                            self.current_field
506                        ),
507                    });
508                }
509                let index = Index::String(String::from(first_key));
510                let reader = HoconRead::new(hc);
511                let deserializer = &mut Deserializer::new(reader);
512                deserializer.current_field = index;
513                visitor.visit_enum(VariantAccess::new(deserializer))
514            }
515            _ => Err(Error {
516                message: format!("invalid type for field \"{}\"", self.current_field),
517            }),
518        }
519    }
520
521    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
522    where
523        V: serde::de::Visitor<'de>,
524    {
525        self.deserialize_str(visitor)
526    }
527
528    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
529    where
530        V: serde::de::Visitor<'de>,
531    {
532        visitor.visit_unit()
533    }
534}
535
536struct SeqAccess<'a, R: 'a> {
537    de: &'a mut Deserializer<R>,
538    current: usize,
539}
540
541impl<'a, R: 'a> SeqAccess<'a, R> {
542    fn new(de: &'a mut Deserializer<R>) -> Self {
543        SeqAccess { de, current: 0 }
544    }
545}
546
547impl<'de, 'a, R: Read + 'a> serde::de::SeqAccess<'de> for SeqAccess<'a, R> {
548    type Error = Error;
549
550    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
551    where
552        T: serde::de::DeserializeSeed<'de>,
553    {
554        self.de.current_field = Index::Number(self.current);
555        self.current += 1;
556        if self
557            .de
558            .read
559            .get_attribute_value(&self.de.current_field)
560            .is_none()
561        {
562            return Ok(None);
563        }
564        seed.deserialize(&mut *self.de).map(Some)
565    }
566}
567
568struct MapAccess<'a, R: 'a> {
569    de: &'a mut Deserializer<R>,
570    keys: Vec<String>,
571    current: usize,
572}
573
574impl<'a, R: 'a> MapAccess<'a, R> {
575    fn new(de: &'a mut Deserializer<R>, keys: Vec<String>) -> Self {
576        de.as_key = true;
577        MapAccess {
578            de,
579            keys,
580            current: 0,
581        }
582    }
583}
584
585impl<'de, 'a, R: Read + 'a> serde::de::MapAccess<'de> for MapAccess<'a, R> {
586    type Error = Error;
587
588    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
589    where
590        K: serde::de::DeserializeSeed<'de>,
591    {
592        if self.current >= self.keys.len() {
593            Ok(None)
594        } else {
595            self.de.current_field = Index::String(self.keys[self.current].to_string());
596            self.de.as_key = true;
597            self.current += 1;
598            seed.deserialize(&mut *self.de).map(Some)
599        }
600    }
601
602    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
603    where
604        V: serde::de::DeserializeSeed<'de>,
605    {
606        self.de.as_key = false;
607        seed.deserialize(&mut *self.de)
608    }
609}
610
611struct VariantAccess<'a, R: 'a> {
612    de: &'a mut Deserializer<R>,
613}
614
615impl<'a, R: 'a> VariantAccess<'a, R> {
616    fn new(de: &'a mut Deserializer<R>) -> Self {
617        de.as_key = true;
618        VariantAccess { de }
619    }
620}
621
622impl<'de, 'a, R: Read + 'a> serde::de::EnumAccess<'de> for VariantAccess<'a, R> {
623    type Error = Error;
624    type Variant = Self;
625
626    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self)>
627    where
628        V: serde::de::DeserializeSeed<'de>,
629    {
630        let val = seed.deserialize(&mut *self.de)?;
631        Ok((val, self))
632    }
633}
634
635impl<'de, 'a, R: Read + 'a> serde::de::VariantAccess<'de> for VariantAccess<'a, R> {
636    type Error = Error;
637
638    fn unit_variant(self) -> Result<()> {
639        serde::de::Deserialize::deserialize(self.de)
640    }
641
642    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
643    where
644        T: serde::de::DeserializeSeed<'de>,
645    {
646        seed.deserialize(self.de)
647    }
648
649    fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
650    where
651        V: serde::de::Visitor<'de>,
652    {
653        serde::de::Deserializer::deserialize_seq(self.de, visitor)
654    }
655
656    fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
657    where
658        V: serde::de::Visitor<'de>,
659    {
660        serde::de::Deserializer::deserialize_struct(self.de, "", fields, visitor)
661    }
662}
663
664struct UnitVariantAccess<'a, R: 'a> {
665    de: &'a mut Deserializer<R>,
666}
667
668impl<'a, R: 'a> UnitVariantAccess<'a, R> {
669    fn new(de: &'a mut Deserializer<R>) -> Self {
670        de.as_key = true;
671        UnitVariantAccess { de }
672    }
673}
674
675impl<'de, 'a, R: Read + 'a> serde::de::EnumAccess<'de> for UnitVariantAccess<'a, R> {
676    type Error = Error;
677    type Variant = Self;
678
679    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self)>
680    where
681        V: serde::de::DeserializeSeed<'de>,
682    {
683        let variant = seed.deserialize(&mut *self.de)?;
684        Ok((variant, self))
685    }
686}
687
688impl<'de, 'a, R: Read + 'a> serde::de::VariantAccess<'de> for UnitVariantAccess<'a, R> {
689    type Error = Error;
690
691    fn unit_variant(self) -> Result<()> {
692        Ok(())
693    }
694
695    fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value>
696    where
697        T: serde::de::DeserializeSeed<'de>,
698    {
699        Err(serde::de::Error::invalid_type(
700            serde::de::Unexpected::UnitVariant,
701            &"newtype variant",
702        ))
703    }
704
705    fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
706    where
707        V: serde::de::Visitor<'de>,
708    {
709        Err(serde::de::Error::invalid_type(
710            serde::de::Unexpected::UnitVariant,
711            &"tuple variant",
712        ))
713    }
714
715    fn struct_variant<V>(self, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value>
716    where
717        V: serde::de::Visitor<'de>,
718    {
719        Err(serde::de::Error::invalid_type(
720            serde::de::Unexpected::UnitVariant,
721            &"struct variant",
722        ))
723    }
724}
725
726fn from_trait<'de, R, T>(read: R) -> Result<T>
727where
728    R: Read,
729    T: serde::de::Deserialize<'de>,
730{
731    let mut de = Deserializer::new(read);
732    let value = serde_path_to_error::deserialize(&mut de)?;
733
734    Ok(value)
735}
736
737pub(crate) fn from_hocon<'de, T>(hocon: Hocon) -> Result<T>
738where
739    T: serde::de::Deserialize<'de>,
740{
741    from_trait(HoconRead::new(hocon))
742}
743
744/// Deserialize a HOCON string directly
745pub fn from_str<'de, T>(hocon: &str) -> std::result::Result<T, crate::Error>
746where
747    T: serde::de::Deserialize<'de>,
748{
749    from_trait(HoconRead::new(
750        crate::HoconLoader::new().load_str(hocon)?.hocon()?,
751    ))
752    .map_err(|err| crate::Error::Deserialization {
753        message: err.message,
754    })
755}
756
757#[cfg(test)]
758#[allow(dead_code)]
759mod tests {
760    use crate::Hocon;
761    use serde::Deserialize;
762    use std::collections::HashMap;
763    use linked_hash_map::LinkedHashMap;
764
765    #[derive(Deserialize, Debug)]
766    struct Simple {
767        int: i64,
768        float: f64,
769        option_int: Option<u64>,
770    }
771    #[derive(Deserialize, Debug)]
772    struct WithSubStruct {
773        vec_sub: Vec<Simple>,
774        int: i32,
775        float: f32,
776        boolean: bool,
777        string: String,
778    }
779
780    #[test]
781    fn can_deserialize_struct() {
782        let mut hm = LinkedHashMap::new();
783        hm.insert(String::from("int"), Hocon::Integer(56));
784        hm.insert(String::from("float"), Hocon::Real(543.12));
785        hm.insert(String::from("boolean"), Hocon::Boolean(false));
786        hm.insert(String::from("string"), Hocon::String(String::from("test")));
787        let mut vec_sub = vec![];
788        let mut subhm = LinkedHashMap::new();
789        subhm.insert(String::from("int"), Hocon::Integer(5));
790        subhm.insert(String::from("float"), Hocon::Integer(6));
791        subhm.insert(String::from("extra"), Hocon::Integer(10));
792        let subdoc = Hocon::Hash(subhm);
793        vec_sub.push(subdoc);
794        let mut subhm = LinkedHashMap::new();
795        subhm.insert(String::from("int"), Hocon::Integer(5));
796        subhm.insert(String::from("float"), Hocon::Integer(6));
797        let subdoc = Hocon::Hash(subhm);
798        vec_sub.push(subdoc);
799        let mut subhm = LinkedHashMap::new();
800        subhm.insert(String::from("int"), Hocon::Integer(5));
801        subhm.insert(String::from("float"), Hocon::Integer(6));
802        subhm.insert(String::from("extra"), Hocon::Null);
803        let subdoc = Hocon::Hash(subhm);
804        vec_sub.push(subdoc);
805        hm.insert(String::from("vec_sub"), Hocon::Array(vec_sub));
806        let doc = Hocon::Hash(hm);
807
808        let res: super::Result<WithSubStruct> = dbg!(super::from_hocon(dbg!(doc)));
809        assert!(res.is_ok());
810    }
811
812    #[test]
813    fn will_fail_on_missing_field() {
814        let mut hm = LinkedHashMap::new();
815        hm.insert(String::from("int"), Hocon::Integer(5));
816        let doc = Hocon::Hash(hm);
817
818        let res: super::Result<Simple> = dbg!(super::from_hocon(dbg!(doc)));
819        assert!(res.is_err());
820    }
821
822    #[test]
823    fn will_not_fail_on_extra_field() {
824        let mut hm = LinkedHashMap::new();
825        hm.insert(String::from("int"), Hocon::Integer(5));
826        hm.insert(String::from("float"), Hocon::Integer(6));
827        hm.insert(String::from("extra"), Hocon::Integer(10));
828        let doc = Hocon::Hash(hm);
829
830        let res: super::Result<Simple> = dbg!(super::from_hocon(dbg!(doc)));
831        assert!(res.is_ok());
832    }
833
834    #[test]
835    fn will_fail_on_wrong_type() {
836        let mut hm = LinkedHashMap::new();
837        hm.insert(String::from("int"), Hocon::Integer(5));
838        hm.insert(String::from("float"), Hocon::String(String::from("wrong")));
839        let doc = Hocon::Hash(hm);
840        let res: super::Result<Simple> = dbg!(super::from_hocon(dbg!(doc)));
841        assert!(res.is_err());
842
843        let mut hm = LinkedHashMap::new();
844        hm.insert(String::from("int"), Hocon::Integer(56));
845        hm.insert(String::from("float"), Hocon::Real(543.12));
846        hm.insert(String::from("boolean"), Hocon::Boolean(false));
847        hm.insert(String::from("string"), Hocon::Array(vec![]));
848        hm.insert(String::from("vec_sub"), Hocon::Array(vec![]));
849        let doc = Hocon::Hash(hm);
850        let res: super::Result<WithSubStruct> = dbg!(super::from_hocon(dbg!(doc)));
851        assert!(res.is_err());
852
853        let mut hm = LinkedHashMap::new();
854        hm.insert(String::from("int"), Hocon::Integer(56));
855        hm.insert(String::from("float"), Hocon::Real(543.12));
856        hm.insert(String::from("boolean"), Hocon::Integer(1));
857        hm.insert(String::from("string"), Hocon::String(String::from("test")));
858        hm.insert(String::from("vec_sub"), Hocon::Array(vec![]));
859        let doc = Hocon::Hash(hm);
860        let res: super::Result<WithSubStruct> = dbg!(super::from_hocon(dbg!(doc)));
861        assert!(res.is_err());
862    }
863
864    #[test]
865    fn access_hash_as_array() {
866        #[derive(Deserialize, Debug)]
867        struct WithArray {
868            a: Vec<i32>,
869        }
870
871        let mut array = LinkedHashMap::new();
872        array.insert(String::from("0"), Hocon::Integer(5));
873        array.insert(String::from("2"), Hocon::Integer(7));
874        let mut hm = LinkedHashMap::new();
875        hm.insert(String::from("a"), Hocon::Hash(array));
876        let doc = Hocon::Hash(hm);
877
878        let res: super::Result<WithArray> = dbg!(super::from_hocon(dbg!(doc)));
879        assert!(res.is_ok());
880        assert_eq!(res.expect("during test").a, vec![5, 7]);
881    }
882
883    #[test]
884    fn hocon_and_serde_default() {
885        #[derive(Deserialize, Debug)]
886        struct MyStructWithDefaultField {
887            #[serde(default)]
888            size: f64,
889        }
890
891        // let s: MyStruct = HoconLoader::new().load_str("").unwrap().resolve().unwrap();
892        let doc = Hocon::Hash(LinkedHashMap::new());
893
894        let res: super::Result<MyStructWithDefaultField> = dbg!(super::from_hocon(dbg!(doc)));
895        assert!(res.is_ok());
896        assert_eq!(res.expect("during test").size, 0.);
897    }
898
899    #[test]
900    fn unit_struct() {
901        #[derive(Deserialize, Debug, PartialEq)]
902        struct UnitStruct;
903
904        #[derive(Deserialize, Debug)]
905        struct MyStruct {
906            item: UnitStruct,
907        }
908
909        let mut hm = LinkedHashMap::new();
910        hm.insert(String::from("item"), Hocon::Null);
911        let doc = Hocon::Hash(hm);
912
913        let res: super::Result<MyStruct> = dbg!(super::from_hocon(dbg!(doc)));
914        assert!(res.is_ok());
915        assert_eq!(res.expect("during test").item, UnitStruct);
916    }
917
918    #[test]
919    fn tuple() {
920        #[derive(Deserialize, Debug)]
921        struct MyStruct {
922            item: (u64, String),
923        }
924
925        let mut hm = LinkedHashMap::new();
926        let mut vec_sub = vec![];
927        vec_sub.push(Hocon::Integer(0));
928        vec_sub.push(Hocon::String(String::from("Hello")));
929        hm.insert(String::from("item"), Hocon::Array(vec_sub));
930        let doc = Hocon::Hash(hm);
931
932        let res: super::Result<MyStruct> = dbg!(super::from_hocon(dbg!(doc)));
933        assert!(res.is_ok());
934        assert_eq!(res.expect("during test").item, (0, "Hello".to_string()));
935    }
936
937    #[test]
938    fn tuple_struct() {
939        #[derive(Deserialize, Debug, PartialEq)]
940        struct TupleStruct(u64, String);
941
942        #[derive(Deserialize, Debug)]
943        struct MyStruct {
944            item: TupleStruct,
945        }
946
947        let mut hm = LinkedHashMap::new();
948        let mut vec_sub = vec![];
949        vec_sub.push(Hocon::Integer(0));
950        vec_sub.push(Hocon::String(String::from("Hello")));
951        hm.insert(String::from("item"), Hocon::Array(vec_sub));
952        let doc = Hocon::Hash(hm);
953
954        let res: super::Result<MyStruct> = dbg!(super::from_hocon(dbg!(doc)));
955        assert!(res.is_ok());
956        assert_eq!(
957            res.expect("during test").item,
958            TupleStruct(0, "Hello".to_string())
959        );
960    }
961
962    #[test]
963    fn map() {
964        #[derive(Deserialize, Debug)]
965        struct MyStruct {
966            item: HashMap<String, u64>,
967        }
968
969        let mut hm = LinkedHashMap::new();
970        let mut hm_sub = LinkedHashMap::new();
971        hm_sub.insert(String::from("Hello"), Hocon::Integer(7));
972        hm.insert(String::from("item"), Hocon::Hash(hm_sub));
973        let doc = Hocon::Hash(hm);
974
975        let res: super::Result<MyStruct> = dbg!(super::from_hocon(dbg!(doc)));
976        assert!(res.is_ok());
977        assert_eq!(res.expect("during test").item.get("Hello"), Some(&7));
978    }
979
980    #[test]
981    fn map_with_enum_keys() {
982        #[derive(Deserialize, Debug, Hash, PartialEq, Eq)]
983        enum E {
984            A,
985            B,
986        }
987
988        let mut hm = LinkedHashMap::new();
989        hm.insert(String::from("A"), Hocon::Integer(1));
990        hm.insert(String::from("B"), Hocon::Integer(2));
991        let doc = Hocon::Hash(hm);
992
993        let res: super::Result<HashMap<E, u8>> = dbg!(super::from_hocon(dbg!(doc)));
994        assert!(res.is_ok());
995        assert_eq!(res.expect("during test").get(&E::A), Some(&1));
996
997        #[derive(Deserialize, Debug)]
998        struct S {
999            s: u8,
1000        }
1001
1002        let mut hm = LinkedHashMap::new();
1003        let mut hm_sub = LinkedHashMap::new();
1004        hm_sub.insert(String::from("s"), Hocon::Integer(7));
1005        hm.insert(String::from("A"), Hocon::Hash(hm_sub));
1006        let doc = Hocon::Hash(hm);
1007
1008        let res: super::Result<HashMap<E, S>> = dbg!(super::from_hocon(dbg!(doc)));
1009        assert!(res.is_ok());
1010        assert_eq!(res.expect("during test").get(&E::A).unwrap().s, 7);
1011    }
1012
1013    #[derive(Deserialize, Debug, PartialEq)]
1014    enum MyEnum {
1015        UnitVariant,
1016        TupleVariant(u64, bool),
1017        StructVariant { u: u64, b: bool },
1018    }
1019
1020    #[derive(Deserialize, Debug)]
1021    struct MyStructWithEnum {
1022        item: MyEnum,
1023    }
1024
1025    #[test]
1026    fn deserialize_unit_enum() {
1027        let mut hm = LinkedHashMap::new();
1028        hm.insert(
1029            String::from("item"),
1030            Hocon::String(String::from("UnitVariant")),
1031        );
1032        let doc = Hocon::Hash(hm);
1033
1034        let res: super::Result<MyStructWithEnum> = dbg!(super::from_hocon(dbg!(doc)));
1035        assert!(res.is_ok());
1036        assert_eq!(res.expect("during test").item, MyEnum::UnitVariant);
1037    }
1038
1039    #[test]
1040    fn deserialize_tuple_enum() {
1041        let mut hm = LinkedHashMap::new();
1042        let mut sub_hm = LinkedHashMap::new();
1043        sub_hm.insert(String::from("u"), Hocon::Integer(12));
1044        sub_hm.insert(String::from("b"), Hocon::Boolean(true));
1045        let mut variant_map = LinkedHashMap::new();
1046        variant_map.insert(String::from("StructVariant"), Hocon::Hash(sub_hm));
1047        hm.insert(String::from("item"), Hocon::Hash(variant_map));
1048        let doc = Hocon::Hash(hm);
1049
1050        let res: super::Result<MyStructWithEnum> = dbg!(super::from_hocon(dbg!(doc)));
1051        assert!(res.is_ok());
1052        assert_eq!(
1053            res.expect("during test").item,
1054            MyEnum::StructVariant { u: 12, b: true }
1055        );
1056    }
1057
1058    #[test]
1059    fn deserialize_struct_enum() {
1060        let mut hm = LinkedHashMap::new();
1061        let mut sub_vec = vec![];
1062        sub_vec.push(Hocon::Integer(7));
1063        sub_vec.push(Hocon::Boolean(false));
1064        let mut variant_map = LinkedHashMap::new();
1065        variant_map.insert(String::from("TupleVariant"), Hocon::Array(sub_vec));
1066        hm.insert(String::from("item"), Hocon::Hash(variant_map));
1067        let doc = Hocon::Hash(hm);
1068
1069        let res: super::Result<MyStructWithEnum> = dbg!(super::from_hocon(dbg!(doc)));
1070        assert!(res.is_ok());
1071        assert_eq!(
1072            res.expect("during test").item,
1073            MyEnum::TupleVariant(7, false)
1074        );
1075    }
1076
1077    #[test]
1078    fn deserialize_tagged_enum() {
1079        #[derive(Debug, Deserialize, PartialEq)]
1080        struct Container {
1081            rp: RetryPolicy,
1082        }
1083        #[derive(Debug, Deserialize, PartialEq)]
1084        #[serde(tag = "type")]
1085        pub enum RetryPolicy {
1086            NoRetry,
1087            Asap { num_retries: u32 },
1088        }
1089
1090        let mut hm = LinkedHashMap::new();
1091        let mut sub_hm = LinkedHashMap::new();
1092        // sub_hm.insert(String::from("type"), Hocon::String(String::from("NoRetry")));
1093        sub_hm.insert(String::from("type"), Hocon::String(String::from("Asap")));
1094        sub_hm.insert(String::from("num_retries"), Hocon::Integer(7));
1095        hm.insert(String::from("rp"), Hocon::Hash(sub_hm));
1096        let doc = Hocon::Hash(hm);
1097
1098        let res: super::Result<Container> = dbg!(super::from_hocon(dbg!(doc)));
1099        assert!(res.is_ok());
1100        assert_eq!(
1101            res.expect("during test").rp,
1102            RetryPolicy::Asap { num_retries: 7 }
1103        );
1104    }
1105}