up_rust/
protobuf_mappable.rs1use super::SerializationError;
15use protobuf::{well_known_types::any::Any, Message, MessageFull};
16
17pub trait ProtobufMappable: Sized {
21 fn parse_from_protobuf_bytes(proto: &[u8]) -> Result<Self, SerializationError>;
31 fn parse_from_packed_protobuf_bytes(proto: &[u8]) -> Result<Self, SerializationError>;
42 fn write_to_protobuf_bytes(&self) -> Result<Vec<u8>, SerializationError>;
48 fn write_to_packed_protobuf_bytes(&self) -> Result<Vec<u8>, SerializationError>;
54}
55
56impl<T: MessageFull> ProtobufMappable for T {
59 fn parse_from_protobuf_bytes(proto: &[u8]) -> Result<Self, SerializationError> {
60 Ok(T::parse_from_bytes(proto)?)
61 }
62
63 fn parse_from_packed_protobuf_bytes(proto: &[u8]) -> Result<Self, SerializationError> {
64 let any = Any::parse_from_bytes(proto)?;
65 match any.unpack() {
66 Ok(Some(v)) => Ok(v),
67 Ok(None) => Err(SerializationError::new(
68 "cannot unpack protobuf, type mismatch".to_string(),
69 )),
70 Err(e) => Err(SerializationError::from(e)),
71 }
72 }
73
74 fn write_to_protobuf_bytes(&self) -> Result<Vec<u8>, SerializationError> {
75 T::write_to_bytes(self).map_err(SerializationError::from)
76 }
77
78 fn write_to_packed_protobuf_bytes(&self) -> Result<Vec<u8>, SerializationError> {
79 Any::pack(self)
80 .and_then(|any| any.write_to_bytes())
81 .map_err(SerializationError::from)
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use protobuf::well_known_types::{timestamp::Timestamp, wrappers::StringValue};
89
90 #[test]
91 fn test_write_to_protobuf_bytes_works_for_message_full() {
92 let payload = StringValue {
93 value: "hello".to_string(),
94 ..Default::default()
95 };
96 let bytes = payload.write_to_protobuf_bytes().unwrap();
97 let deserialized = StringValue::parse_from_protobuf_bytes(&bytes).unwrap();
98 assert_eq!(deserialized.value, "hello");
99 }
100
101 #[test]
102 fn test_write_to_packed_protobuf_bytes_works_for_message_full() {
103 let payload = StringValue {
104 value: "hello".to_string(),
105 ..Default::default()
106 };
107 let bytes = payload.write_to_packed_protobuf_bytes().unwrap();
108 let deserialized = StringValue::parse_from_packed_protobuf_bytes(&bytes).unwrap();
109 assert_eq!(deserialized.value, "hello");
110 }
111
112 #[test]
113 fn test_parse_from_packed_protobuf_bytes_fails_for_wrong_message_type() {
114 let payload = StringValue {
115 value: "hello".to_string(),
116 ..Default::default()
117 };
118 let bytes = payload.write_to_packed_protobuf_bytes().unwrap();
119 assert!(Timestamp::parse_from_packed_protobuf_bytes(&bytes)
120 .is_err_and(|e| { matches!(e, SerializationError { .. }) }));
121 }
122}