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}