1 use crate::parse_from_bytes;
2 use crate::reflect::MessageDescriptor;
3 use crate::well_known_types::Any;
4 use crate::Message;
5 use crate::ProtobufResult;
6 
7 impl Any {
type_url(type_url_prefix: &str, descriptor: &MessageDescriptor) -> String8     fn type_url(type_url_prefix: &str, descriptor: &MessageDescriptor) -> String {
9         format!("{}/{}", type_url_prefix, descriptor.full_name())
10     }
11 
get_type_name_from_type_url(type_url: &str) -> Option<&str>12     fn get_type_name_from_type_url(type_url: &str) -> Option<&str> {
13         match type_url.rfind('/') {
14             Some(i) => Some(&type_url[i + 1..]),
15             None => None,
16         }
17     }
18 
19     /// Pack any message into `well_known_types::Any` value.
20     ///
21     /// # Examples
22     ///
23     /// ```
24     /// # use protobuf::Message;
25     /// # use protobuf::ProtobufResult;
26     /// use protobuf::well_known_types::Any;
27     ///
28     /// # fn the_test<MyMessage: Message>(message: &MyMessage) -> ProtobufResult<()> {
29     /// let message: &MyMessage = message;
30     /// let any = Any::pack(message)?;
31     /// assert!(any.is::<MyMessage>());
32     /// #   Ok(())
33     /// # }
34     /// ```
pack<M: Message>(message: &M) -> ProtobufResult<Any>35     pub fn pack<M: Message>(message: &M) -> ProtobufResult<Any> {
36         Any::pack_dyn(message)
37     }
38 
39     /// Pack any message into `well_known_types::Any` value.
40     ///
41     /// # Examples
42     ///
43     /// ```
44     /// use protobuf::Message;
45     /// # use protobuf::ProtobufResult;
46     /// use protobuf::well_known_types::Any;
47     ///
48     /// # fn the_test(message: &dyn Message) -> ProtobufResult<()> {
49     /// let message: &dyn Message = message;
50     /// let any = Any::pack_dyn(message)?;
51     /// assert!(any.is_dyn(message.descriptor()));
52     /// #   Ok(())
53     /// # }
54     /// ```
pack_dyn(message: &dyn Message) -> ProtobufResult<Any>55     pub fn pack_dyn(message: &dyn Message) -> ProtobufResult<Any> {
56         Any::pack_with_type_url_prefix(message, "type.googleapis.com")
57     }
58 
pack_with_type_url_prefix( message: &dyn Message, type_url_prefix: &str, ) -> ProtobufResult<Any>59     fn pack_with_type_url_prefix(
60         message: &dyn Message,
61         type_url_prefix: &str,
62     ) -> ProtobufResult<Any> {
63         Ok(Any {
64             type_url: Any::type_url(type_url_prefix, message.descriptor()),
65             value: message.write_to_bytes()?,
66             ..Default::default()
67         })
68     }
69 
70     /// Check if `Any` contains a message of given type.
is<M: Message>(&self) -> bool71     pub fn is<M: Message>(&self) -> bool {
72         self.is_dyn(M::descriptor_static())
73     }
74 
75     /// Check if `Any` contains a message of given type.
is_dyn(&self, descriptor: &MessageDescriptor) -> bool76     pub fn is_dyn(&self, descriptor: &MessageDescriptor) -> bool {
77         match Any::get_type_name_from_type_url(&self.type_url) {
78             Some(type_name) => type_name == descriptor.full_name(),
79             None => false,
80         }
81     }
82 
83     /// Extract a message from this `Any`.
84     ///
85     /// # Returns
86     ///
87     /// * `Ok(None)` when message type mismatch
88     /// * `Err` when parse failed
unpack<M: Message>(&self) -> ProtobufResult<Option<M>>89     pub fn unpack<M: Message>(&self) -> ProtobufResult<Option<M>> {
90         if !self.is::<M>() {
91             return Ok(None);
92         }
93         Ok(Some(parse_from_bytes(&self.value)?))
94     }
95 
96     /// Extract a message from this `Any`.
97     ///
98     /// # Returns
99     ///
100     /// * `Ok(None)` when message type mismatch
101     /// * `Err` when parse failed
unpack_dyn( &self, descriptor: &MessageDescriptor, ) -> ProtobufResult<Option<Box<dyn Message>>>102     pub fn unpack_dyn(
103         &self,
104         descriptor: &MessageDescriptor,
105     ) -> ProtobufResult<Option<Box<dyn Message>>> {
106         if !self.is_dyn(descriptor) {
107             return Ok(None);
108         }
109         let mut message = descriptor.new_instance();
110         message.merge_from_bytes(&self.value)?;
111         message.check_initialized()?;
112         Ok(Some(message))
113     }
114 }
115