google_cloud_wkt/
message.rs1pub(crate) type Map = serde_json::Map<String, serde_json::Value>;
18use crate::AnyError as Error;
19
20pub trait Message {
26 fn typename() -> &'static str;
28
29 fn to_map(&self) -> Result<Map, Error>
31 where
32 Self: serde::ser::Serialize + Sized,
33 {
34 to_json_object(self)
35 }
36
37 fn from_map(map: &Map) -> Result<Self, Error>
39 where
40 Self: serde::de::DeserializeOwned,
41 {
42 let map: Map = map
43 .iter()
44 .filter_map(|(k, v)| {
45 if k == "@type" {
46 return None;
47 }
48 Some((k.clone(), v.clone()))
49 })
50 .collect();
51 serde_json::from_value::<Self>(serde_json::Value::Object(map)).map_err(Error::deser)
52 }
53}
54
55pub(crate) fn to_json_object<T>(message: &T) -> Result<Map, Error>
56where
57 T: Message + serde::ser::Serialize,
58{
59 use serde_json::Value;
60
61 let value = serde_json::to_value(message).map_err(Error::ser)?;
62 match value {
63 Value::Object(mut map) => {
64 map.insert(
65 "@type".to_string(),
66 Value::String(T::typename().to_string()),
67 );
68 Ok(map)
69 }
70 _ => Err(unexpected_json_type()),
71 }
72}
73
74pub(crate) fn to_json_string<T>(message: &T) -> Result<Map, Error>
75where
76 T: Message + serde::ser::Serialize,
77{
78 use serde_json::Value;
79 let value = serde_json::to_value(message).map_err(Error::ser)?;
80 match value {
81 Value::String(s) => {
82 let map: Map = [("@type", T::typename().to_string()), ("value", s)]
86 .into_iter()
87 .map(|(k, v)| (k.to_string(), Value::String(v)))
88 .collect();
89 Ok(map)
90 }
91 _ => Err(unexpected_json_type()),
92 }
93}
94
95pub(crate) fn from_value<T>(map: &Map) -> Result<T, Error>
96where
97 T: serde::de::DeserializeOwned,
98{
99 map.get("value")
100 .map(|v| serde_json::from_value::<T>(v.clone()))
101 .ok_or_else(missing_value_field)?
102 .map_err(Error::deser)
103}
104
105pub(crate) fn missing_value_field() -> Error {
106 Error::deser("value field is missing")
107}
108
109fn unexpected_json_type() -> Error {
110 Error::ser("unexpected JSON type, only Object and String are supported")
111}
112
113#[cfg(test)]
114mod test {
115 use super::*;
116 use serde_json::json;
117
118 #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
119 struct TestMessage {
120 #[serde(flatten)]
121 _unknown_fields: serde_json::Map<String, serde_json::Value>,
122 }
123
124 impl Message for TestMessage {
125 fn typename() -> &'static str {
126 "TestMessage"
127 }
128 }
129
130 #[test]
131 fn drop_type_field() {
132 let input = json!({
133 "@type": "TestMessage",
134 "a": 1,
135 "b": 2,
136 });
137 let map = input.as_object().cloned().unwrap();
138 let test = TestMessage::from_map(&map).unwrap();
139 assert!(test._unknown_fields.get("@type").is_none(), "{test:?}");
140 }
141}