pbjson_types/
struct.rs

1use crate::Struct;
2
3impl From<std::collections::HashMap<String, crate::Value>> for Struct {
4    fn from(fields: std::collections::HashMap<String, crate::Value>) -> Self {
5        Self { fields }
6    }
7}
8
9impl FromIterator<(String, crate::Value)> for Struct {
10    fn from_iter<T>(iter: T) -> Self
11    where
12        T: IntoIterator<Item = (String, crate::Value)>,
13    {
14        Self {
15            fields: iter.into_iter().collect(),
16        }
17    }
18}
19
20impl serde::Serialize for Struct {
21    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
22    where
23        S: serde::Serializer,
24    {
25        self.fields.serialize(ser)
26    }
27}
28
29impl<'de> serde::Deserialize<'de> for Struct {
30    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31    where
32        D: serde::Deserializer<'de>,
33    {
34        deserializer.deserialize_map(StructVisitor)
35    }
36}
37
38struct StructVisitor;
39
40impl<'de> serde::de::Visitor<'de> for StructVisitor {
41    type Value = Struct;
42
43    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        formatter.write_str("google.protobuf.Struct")
45    }
46
47    fn visit_map<A>(self, mut map_access: A) -> Result<Self::Value, A::Error>
48    where
49        A: serde::de::MapAccess<'de>,
50    {
51        let mut map = std::collections::HashMap::new();
52
53        while let Some((key, value)) = map_access.next_entry()? {
54            map.insert(key, value);
55        }
56
57        Ok(map.into())
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    #[test]
64    fn it_works() {
65        let map: crate::Struct = std::collections::HashMap::from([
66            (String::from("bool"), crate::Value::from(true)),
67            (
68                String::from("unit"),
69                crate::value::Kind::NullValue(0).into(),
70            ),
71            (String::from("number"), 5.0.into()),
72            (String::from("string"), "string".into()),
73            (String::from("list"), vec![1.0.into(), 2.0.into()].into()),
74            (
75                String::from("map"),
76                std::collections::HashMap::from([(String::from("key"), "value".into())]).into(),
77            ),
78        ])
79        .into();
80
81        assert_eq!(
82            serde_json::to_value(map).unwrap(),
83            serde_json::json!({
84                "bool": true,
85                "unit": null,
86                "number": 5.0,
87                "string": "string",
88                "list": [1.0, 2.0],
89                "map": {
90                    "key": "value",
91                }
92            })
93        );
94    }
95}