1#[derive(Clone, Debug, Default, PartialEq)]
54#[non_exhaustive]
55pub struct Any(serde_json::Map<String, serde_json::Value>);
56
57#[derive(thiserror::Error, Debug)]
59pub enum AnyError {
60 #[error("cannot serialize object into an Any, source={0:?}")]
62 SerializationError(#[source] BoxedError),
63
64 #[error("cannot deserialize from an Any, source={0:?}")]
66 DeserializationError(#[source] BoxedError),
67
68 #[error("expected type mismatch in Any deserialization type={0}")]
70 TypeMismatchError(String),
71}
72
73impl AnyError {
74 pub(crate) fn ser<T: Into<BoxedError>>(v: T) -> Self {
75 Self::SerializationError(v.into())
76 }
77
78 pub(crate) fn deser<T: Into<BoxedError>>(v: T) -> Self {
79 Self::DeserializationError(v.into())
80 }
81}
82
83type BoxedError = Box<dyn std::error::Error + Send + Sync>;
84type Error = AnyError;
85
86impl Any {
87 pub fn try_from<T>(message: &T) -> Result<Self, Error>
90 where
91 T: serde::ser::Serialize + crate::message::Message,
92 {
93 let value = message.to_map()?;
94 Ok(Any(value))
95 }
96
97 pub fn try_into_message<T>(&self) -> Result<T, Error>
99 where
100 T: serde::de::DeserializeOwned + crate::message::Message,
101 {
102 let map = &self.0;
103 let r#type = map
104 .get("@type")
105 .and_then(|v| v.as_str())
106 .ok_or_else(|| "@type field is missing or is not a string".to_string())
107 .map_err(Error::deser)?;
108 Self::check_typename(r#type, T::typename())?;
109 T::from_map(map)
110 }
111
112 fn check_typename(got: &str, want: &str) -> Result<(), Error> {
113 if got == want {
114 return Ok(());
115 }
116 Err(Error::deser(format!("mismatched typenames extracting from Any, the any has {got}, the target type is {want}")))
117 }
118}
119
120impl crate::message::Message for Any {
121 fn typename() -> &'static str {
122 "type.googleapis.com/google.protobuf.Any"
123 }
124 fn to_map(&self) -> Result<crate::message::Map, crate::AnyError> {
125 use serde_json::Value;
126 let map = [
127 ("@type", Value::String(Self::typename().into())),
128 ("value", Value::Object(self.0.clone())),
129 ]
130 .into_iter()
131 .map(|(k, v)| (k.to_string(), v))
132 .collect::<crate::message::Map>();
133 Ok(map)
134 }
135 fn from_map(map: &crate::message::Map) -> Result<Self, crate::AnyError> {
136 crate::message::from_value(map)
137 }
138}
139
140impl serde::ser::Serialize for Any {
142 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
143 where
144 S: serde::ser::Serializer,
145 {
146 self.0.serialize(serializer)
147 }
148}
149
150impl<'de> serde::de::Deserialize<'de> for Any {
152 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
153 where
154 D: serde::Deserializer<'de>,
155 {
156 let value = serde_json::Map::<String, serde_json::Value>::deserialize(deserializer)?;
157 Ok(Any(value))
158 }
159}
160
161#[cfg(test)]
162mod test {
163 use super::*;
164 use crate::duration::*;
165 use crate::empty::Empty;
166 use crate::field_mask::*;
167 use crate::timestamp::*;
168 use serde_json::json;
169 type Result = std::result::Result<(), Box<dyn std::error::Error>>;
170
171 #[derive(Clone, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize)]
172 #[serde(rename_all = "camelCase")]
173 #[non_exhaustive]
174 pub struct Stored {
175 #[serde(skip_serializing_if = "String::is_empty")]
176 pub parent: String,
177 #[serde(skip_serializing_if = "String::is_empty")]
178 pub id: String,
179 }
180
181 impl crate::message::Message for Stored {
182 fn typename() -> &'static str {
183 "type.googleapis.com/wkt.test.Stored"
184 }
185 }
186
187 #[test]
188 fn serialize_duration() -> Result {
189 let d = Duration::clamp(60, 0);
190 let any = Any::try_from(&d)?;
191 let got = serde_json::to_value(any)?;
192 let want = json!({"@type": "type.googleapis.com/google.protobuf.Duration", "value": "60s"});
193 assert_eq!(got, want);
194 Ok(())
195 }
196
197 #[test]
198 fn deserialize_duration() -> Result {
199 let input =
200 json!({"@type": "type.googleapis.com/google.protobuf.Duration", "value": "60s"});
201 let any = Any(input.as_object().unwrap().clone());
202 let d = any.try_into_message::<Duration>()?;
203 assert_eq!(d, Duration::clamp(60, 0));
204 Ok(())
205 }
206
207 #[test]
208 fn serialize_empty() -> Result {
209 let empty = Empty::default();
210 let any = Any::try_from(&empty)?;
211 let got = serde_json::to_value(any)?;
212 let want = json!({"@type": "type.googleapis.com/google.protobuf.Empty"});
213 assert_eq!(got, want);
214 Ok(())
215 }
216
217 #[test]
218 fn deserialize_empty() -> Result {
219 let input = json!({"@type": "type.googleapis.com/google.protobuf.Empty"});
220 let any = Any(input.as_object().unwrap().clone());
221 let empty = any.try_into_message::<Empty>()?;
222 assert_eq!(empty, Empty::default());
223 Ok(())
224 }
225
226 #[test]
227 fn serialize_field_mask() -> Result {
228 let d = FieldMask::default().set_paths(["a", "b"].map(str::to_string).to_vec());
229 let any = Any::try_from(&d)?;
230 let got = serde_json::to_value(any)?;
231 let want =
232 json!({"@type": "type.googleapis.com/google.protobuf.FieldMask", "paths": "a,b"});
233 assert_eq!(got, want);
234 Ok(())
235 }
236
237 #[test]
238 fn deserialize_field_mask() -> Result {
239 let input =
240 json!({"@type": "type.googleapis.com/google.protobuf.FieldMask", "paths": "a,b"});
241 let any = Any(input.as_object().unwrap().clone());
242 let d = any.try_into_message::<FieldMask>()?;
243 assert_eq!(
244 d,
245 FieldMask::default().set_paths(["a", "b"].map(str::to_string).to_vec())
246 );
247 Ok(())
248 }
249
250 #[test]
251 fn serialize_timestamp() -> Result {
252 let d = Timestamp::clamp(123, 0);
253 let any = Any::try_from(&d)?;
254 let got = serde_json::to_value(any)?;
255 let want = json!({"@type": "type.googleapis.com/google.protobuf.Timestamp", "value": "1970-01-01T00:02:03Z"});
256 assert_eq!(got, want);
257 Ok(())
258 }
259
260 #[test]
261 fn deserialize_timestamp() -> Result {
262 let input = json!({"@type": "type.googleapis.com/google.protobuf.Timestamp", "value": "1970-01-01T00:02:03Z"});
263 let any = Any(input.as_object().unwrap().clone());
264 let d = any.try_into_message::<Timestamp>()?;
265 assert_eq!(d, Timestamp::clamp(123, 0));
266 Ok(())
267 }
268
269 #[test]
270 fn serialize_generic() -> Result {
271 let d = Stored {
272 parent: "parent".to_string(),
273 id: "id".to_string(),
274 };
275 let any = Any::try_from(&d)?;
276 let got = serde_json::to_value(any)?;
277 let want =
278 json!({"@type": "type.googleapis.com/wkt.test.Stored", "parent": "parent", "id": "id"});
279 assert_eq!(got, want);
280 Ok(())
281 }
282
283 #[test]
284 fn deserialize_generic() -> Result {
285 let input =
286 json!({"@type": "type.googleapis.com/wkt.test.Stored", "parent": "parent", "id": "id"});
287 let any = Any(input.as_object().unwrap().clone());
288 let d = any.try_into_message::<Stored>()?;
289 assert_eq!(
290 d,
291 Stored {
292 parent: "parent".to_string(),
293 id: "id".to_string()
294 }
295 );
296 Ok(())
297 }
298
299 #[derive(Default, serde::Serialize, serde::Deserialize)]
300 struct DetectBadMessages(serde_json::Value);
301 impl crate::message::Message for DetectBadMessages {
302 fn typename() -> &'static str {
303 "not used"
304 }
305 }
306
307 #[test]
308 fn try_from_error() -> Result {
309 let input = DetectBadMessages(json!([2, 3]));
310 let got = Any::try_from(&input);
311 assert!(got.is_err(), "{got:?}");
312
313 Ok(())
314 }
315
316 #[test]
317 fn deserialize_missing_type_field() -> Result {
318 let input = json!({"@type-is-missing": ""});
319 let any = serde_json::from_value::<Any>(input)?;
320 let got = any.try_into_message::<Stored>();
321 assert!(got.is_err());
322 Ok(())
323 }
324
325 #[test]
326 fn deserialize_invalid_type_field() -> Result {
327 let input = json!({"@type": [1, 2, 3]});
328 let any = serde_json::from_value::<Any>(input)?;
329 let got = any.try_into_message::<Stored>();
330 assert!(got.is_err());
331 Ok(())
332 }
333
334 #[test]
335 fn deserialize_missing_value_field() -> Result {
336 let input = json!({"@type": "type.googleapis.com/google.protobuf.Duration", "value-is-missing": "1.2s"});
337 let any = serde_json::from_value::<Any>(input)?;
338 let got = any.try_into_message::<Duration>();
339 assert!(got.is_err());
340 Ok(())
341 }
342
343 #[test]
344 fn deserialize_invalid_value_field() -> Result {
345 let input =
346 json!({"@type": "type.googleapis.com/google.protobuf.Duration", "value": ["1.2s"]});
347 let any = serde_json::from_value::<Any>(input)?;
348 let got = any.try_into_message::<Duration>();
349 assert!(got.is_err());
350 Ok(())
351 }
352
353 #[test]
354 fn deserialize_type_mismatch() -> Result {
355 let input =
356 json!({"@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.2s"});
357 let any = serde_json::from_value::<Any>(input)?;
358 let got = any.try_into_message::<Timestamp>();
359 assert!(got.is_err());
360 let error = got.err().unwrap();
361 assert!(
362 format!("{error}").contains("type.googleapis.com/google.protobuf.Duration"),
363 "{error}"
364 );
365 assert!(
366 format!("{error}").contains("type.googleapis.com/google.protobuf.Timestamp"),
367 "{error}"
368 );
369 Ok(())
370 }
371}