1use crate::DefaultEncoding;
7use crate::DescribedProtobuf;
8use crate::Error;
9use crate::MessageDecode;
10use crate::MessageEncode;
11use crate::Protobuf;
12use crate::decode;
13use crate::encode;
14use crate::encoding::MessageEncoding;
15use crate::inplace::InplaceOption;
16use crate::protobuf::MessageReader;
17use crate::protobuf::MessageSizer;
18use crate::protobuf::MessageWriter;
19use crate::protofile::DescribeField;
20use crate::protofile::FieldType;
21use crate::protofile::MessageDescription;
22use crate::table::DescribeTable;
23use alloc::string::String;
24use alloc::string::ToString;
25use alloc::vec::Vec;
26use thiserror::Error;
27
28#[derive(Debug)]
33pub struct ProtobufMessage(Vec<u8>);
34
35impl ProtobufMessage {
36 pub fn new(data: impl Protobuf) -> Self {
38 Self(encode(data))
39 }
40
41 pub fn parse<T: Protobuf>(&self) -> Result<T, Error> {
43 decode(&self.0)
44 }
45}
46
47impl DefaultEncoding for ProtobufMessage {
48 type Encoding = MessageEncoding<ProtobufMessageEncoding>;
49}
50
51impl DescribeField<ProtobufMessage> for MessageEncoding<ProtobufMessageEncoding> {
52 const FIELD_TYPE: FieldType<'static> = FieldType::builtin("bytes");
53}
54
55#[derive(Debug)]
57pub struct ProtobufMessageEncoding;
58
59impl<R> MessageEncode<ProtobufMessage, R> for ProtobufMessageEncoding {
60 fn write_message(item: ProtobufMessage, mut writer: MessageWriter<'_, '_, R>) {
61 writer.bytes(&item.0);
62 }
63
64 fn compute_message_size(item: &mut ProtobufMessage, mut sizer: MessageSizer<'_>) {
65 sizer.bytes(item.0.len());
66 }
67}
68
69impl<R> MessageDecode<'_, ProtobufMessage, R> for ProtobufMessageEncoding {
70 fn read_message(
71 item: &mut InplaceOption<'_, ProtobufMessage>,
72 reader: MessageReader<'_, '_, R>,
73 ) -> crate::Result<()> {
74 item.get_or_insert_with(|| ProtobufMessage(Vec::new()))
75 .0
76 .extend(reader.bytes());
77 Ok(())
78 }
79}
80
81#[derive(Debug, Protobuf)]
85pub struct ProtobufAny {
86 #[mesh(1)]
87 type_url: String, #[mesh(2)]
89 value: ProtobufMessage,
90}
91
92#[derive(Debug, Error)]
93#[error("protobuf type mismatch, expected {expected}, got {actual}")]
94struct TypeMismatch {
95 expected: String,
96 actual: String,
97}
98
99impl DescribeTable for ProtobufAny {
100 const DESCRIPTION: MessageDescription<'static> = MessageDescription::External {
101 name: "google.protobuf.Any",
102 import_path: "google/protobuf/any.proto",
103 };
104}
105
106impl ProtobufAny {
107 pub fn new<T: DescribedProtobuf>(data: T) -> Self {
109 Self {
110 type_url: T::TYPE_URL.to_string(),
111 value: ProtobufMessage::new(data),
112 }
113 }
114
115 pub fn parse<T: DescribedProtobuf>(&self) -> Result<T, Error> {
119 if &T::TYPE_URL != self.type_url.as_str() {
120 return Err(Error::new(TypeMismatch {
121 expected: T::TYPE_URL.to_string(),
122 actual: self.type_url.clone(),
123 }));
124 }
125 self.value.parse()
126 }
127
128 pub fn is_message<T: DescribedProtobuf>(&self) -> bool {
130 &T::TYPE_URL == self.type_url.as_str()
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 extern crate std;
137
138 use crate::Protobuf;
139 use crate::encode;
140 use crate::message::ProtobufAny;
141 use crate::message::ProtobufMessage;
142 use crate::tests::as_expect_str;
143 use expect_test::expect;
144 use std::println;
145
146 #[test]
147 fn test_message() {
148 let message = (5u32,);
149
150 assert_eq!(
152 ProtobufMessage::new(message).parse::<(u32,)>().unwrap(),
153 message
154 );
155
156 let expected = expect!([r#"
157 1: varint 5
158 raw: 0805"#]);
159 let actual = encode(ProtobufMessage::new(message));
160 expected.assert_eq(&as_expect_str(&actual));
161
162 assert_eq!(actual, encode(message));
164 }
165
166 #[test]
167 fn test_any() {
168 #[derive(Protobuf, PartialEq, Eq, Copy, Clone, Debug)]
169 #[mesh(package = "test")]
170 struct Message {
171 #[mesh(1)]
172 x: u32,
173 }
174
175 #[derive(Protobuf, Debug)]
176 #[mesh(package = "test")]
177 struct Other {
178 #[mesh(1)]
179 x: u32,
180 }
181
182 let msg = Message { x: 5 };
183 let any = ProtobufAny::new(msg);
184
185 assert_eq!(any.type_url, "type.googleapis.com/test.Message");
186 assert!(any.is_message::<Message>());
187 assert!(!any.is_message::<Other>());
188 assert_eq!(any.parse::<Message>().unwrap(), msg);
189 println!("{:?}", any.parse::<Other>().unwrap_err());
190 }
191}