1use 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!(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 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
744pub 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 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("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}