hocon_rs/serde/
de.rs

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    // 我们只需要实现 `deserialize_any`,其他都用默认的转发实现即可
80    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}