prost_types/
any.rs

1use super::*;
2
3impl Any {
4    /// Serialize the given message type `M` as [`Any`].
5    pub fn from_msg<M>(msg: &M) -> Result<Self, EncodeError>
6    where
7        M: Name,
8    {
9        let type_url = M::type_url();
10        let mut value = Vec::new();
11        Message::encode(msg, &mut value)?;
12        Ok(Any { type_url, value })
13    }
14
15    /// Decode the given message type `M` from [`Any`], validating that it has
16    /// the expected type URL.
17    pub fn to_msg<M>(&self) -> Result<M, DecodeError>
18    where
19        M: Default + Name + Sized,
20    {
21        let expected_type_url = M::type_url();
22        let actual_type_url = &self.type_url;
23
24        if let (Some(expected), Some(actual)) = (
25            TypeUrl::new(&expected_type_url),
26            TypeUrl::new(actual_type_url),
27        ) {
28            if expected == actual {
29                return M::decode(self.value.as_slice());
30            }
31        }
32
33        Err(DecodeError::new_unexpected_type_url(
34            actual_type_url,
35            expected_type_url,
36        ))
37    }
38}
39
40impl Name for Any {
41    const PACKAGE: &'static str = PACKAGE;
42    const NAME: &'static str = "Any";
43
44    fn type_url() -> String {
45        type_url_for::<Self>()
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52    use prost::{bytes, encoding, Message};
53
54    #[test]
55    fn check_any_serialization() {
56        let message = Timestamp::date(2000, 1, 1).unwrap();
57        let any = Any::from_msg(&message).unwrap();
58        assert_eq!(
59            &any.type_url,
60            "type.googleapis.com/google.protobuf.Timestamp"
61        );
62
63        let message2 = any.to_msg::<Timestamp>().unwrap();
64        assert_eq!(message, message2);
65
66        // Wrong type URL
67        assert!(any.to_msg::<Duration>().is_err());
68    }
69    #[derive(Clone, PartialEq, Debug, Default)]
70    struct Test {
71        value: i32,
72    }
73
74    impl Message for Test {
75        fn encode_raw(&self, buf: &mut impl bytes::BufMut) {
76            encoding::int32::encode(1, &self.value, buf);
77        }
78
79        fn merge_field(
80            &mut self,
81            tag: u32,
82            wire_type: encoding::WireType,
83            buf: &mut impl bytes::Buf,
84            ctx: encoding::DecodeContext,
85        ) -> Result<(), crate::DecodeError> {
86            if tag == 1 {
87                encoding::int32::merge(wire_type, &mut self.value, buf, ctx)
88            } else {
89                encoding::skip_field(wire_type, tag, buf, ctx)
90            }
91        }
92
93        fn encoded_len(&self) -> usize {
94            encoding::int32::encoded_len(1, &self.value)
95        }
96
97        fn clear(&mut self) {
98            self.value = 0;
99        }
100    }
101
102    impl crate::Name for Test {
103        const PACKAGE: &'static str = ""; // Empty package
104        const NAME: &'static str = "Test";
105    }
106
107    #[test]
108    fn dynamic_cast_round_trip() {
109        let msg = Test::default();
110        let any = Any::from_msg(&msg).unwrap();
111        let result: Result<Test, _> = any.to_msg();
112        result.expect("This should parse!");
113    }
114
115    #[test]
116    fn default_type_url_should_parse() {
117        let type_url = Test::type_url(); //any.type_url;
118        TypeUrl::new(&type_url)
119            .expect("The URL created by the default implementation should parse");
120    }
121}