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