1use crate::value::Value;
2use serde::{
3 Deserializer,
4 de::{DeserializeSeed, IntoDeserializer, MapAccess, SeqAccess, Visitor},
5 forward_to_deserialize_any,
6};
7
8impl<'de> Deserializer<'de> for Value {
9 type Error = crate::error::Error;
10
11 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
12 where
13 V: Visitor<'de>,
14 {
15 match self {
16 Value::Null => visitor.visit_unit(),
17 Value::Boolean(b) => visitor.visit_bool(b),
18 Value::String(s) => visitor.visit_string(s),
19 Value::Number(n) => n
20 .deserialize_any(visitor)
21 .map_err(|e| crate::error::Error::DeserializeError(e.to_string())),
22 Value::Array(arr) => {
23 struct SeqDeserializer {
24 iter: std::vec::IntoIter<Value>,
25 }
26 impl<'de> SeqAccess<'de> for SeqDeserializer {
27 type Error = crate::error::Error;
28 fn next_element_seed<T>(
29 &mut self,
30 seed: T,
31 ) -> Result<Option<T::Value>, Self::Error>
32 where
33 T: DeserializeSeed<'de>,
34 {
35 match self.iter.next() {
36 Some(val) => seed.deserialize(val).map(Some),
37 None => Ok(None),
38 }
39 }
40 }
41 visitor.visit_seq(SeqDeserializer {
42 iter: arr.into_iter(),
43 })
44 }
45 Value::Object(map) => {
46 struct MapDeserializer {
47 iter: std::collections::hash_map::IntoIter<String, Value>,
48 value: Option<Value>,
49 }
50 impl<'de> MapAccess<'de> for MapDeserializer {
51 type Error = crate::error::Error;
52 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
53 where
54 K: DeserializeSeed<'de>,
55 {
56 match self.iter.next() {
57 Some((k, v)) => {
58 self.value = Some(v);
59 seed.deserialize(k.into_deserializer()).map(Some)
60 }
61 None => Ok(None),
62 }
63 }
64 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
65 where
66 V: DeserializeSeed<'de>,
67 {
68 seed.deserialize(self.value.take().unwrap())
69 }
70 }
71 visitor.visit_map(MapDeserializer {
72 iter: map.into_iter(),
73 value: None,
74 })
75 }
76 }
77 }
78
79 forward_to_deserialize_any! {
81 bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
82 bytes byte_buf option unit unit_struct newtype_struct seq tuple
83 tuple_struct map struct enum identifier ignored_any
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use serde::Deserialize;
90
91 #[derive(Debug, Deserialize, Eq, PartialEq)]
92 struct Config {
93 app: App,
94 deployment: Deployment,
95 }
96
97 #[derive(Debug, Deserialize, Eq, PartialEq)]
98 struct App {
99 name: String,
100 version: String,
101 database: Database,
102 servers: Vec<Server>,
103 log_dir: String,
104 features: Features,
105 }
106
107 #[derive(Debug, Deserialize, Eq, PartialEq)]
108 struct Database {
109 host: String,
110 port: u16,
111 user: String,
112 password: String,
113 options: DatabaseOptions,
114 }
115
116 #[derive(Debug, Deserialize, Eq, PartialEq)]
117 struct DatabaseOptions {
118 ssl: bool,
119 timeout: u32,
120 }
121
122 #[derive(Debug, Deserialize, Eq, PartialEq)]
123 struct Server {
124 host: String,
125 roles: Vec<String>,
126 }
127
128 #[derive(Debug, Deserialize, Eq, PartialEq)]
129 struct Features {
130 experimental: bool,
131 max_connections: u32,
132 tags: Vec<String>,
133 }
134
135 #[derive(Debug, Deserialize, Eq, PartialEq)]
136 struct Deployment {
137 replicas: u32,
138 image: String,
139 }
140 #[test]
141 fn test_de() -> crate::Result<()> {
142 let config_hocon: Config = crate::config::Config::load("resources/deserialize.conf", None)?;
143 let file = std::fs::File::open("resources/deserialize.json").unwrap();
144 let config_json: Config = serde_json::from_reader(file)?;
145 assert_eq!(config_hocon, config_json);
146 Ok(())
147 }
148}