1use crate::Result;
20use crate::field::{Field, FieldValue};
21use crate::tag::Tag;
22use crate::varint::{Varint, WriteExtVarint};
23use crate::wire_format::WireType;
24use ::std::io::Write;
25
26pub trait WriteExtProtobuf {
31 fn write_protobuf_field<L: AsRef<[u8]>>(&mut self, field: &Field<L>) -> Result<usize>;
53
54 fn write_protobuf_fields<'a, L: AsRef<[u8]> + 'a, I>(&mut self, fields: I) -> Result<usize>
75 where
76 I: IntoIterator<Item = &'a Field<L>>;
77}
78
79impl<W> WriteExtProtobuf for W
80where
81 W: Write,
82{
83 fn write_protobuf_field<L: AsRef<[u8]>>(&mut self, field: &Field<L>) -> Result<usize> {
84 let mut bytes_written = 0;
85
86 let wire_type = match &field.value {
88 FieldValue::Varint(_) => WireType::Varint,
89 FieldValue::I32(_) => WireType::Int32,
90 FieldValue::I64(_) => WireType::Int64,
91 FieldValue::Len(_) => WireType::Len,
92 };
93 let tag = Tag {
94 field_number: field.field_number,
95 wire_type,
96 };
97 let tag_varint = tag.to_encoded();
98 bytes_written += self.write_varint(&tag_varint)?;
99
100 match &field.value {
102 FieldValue::Varint(varint) => {
103 bytes_written += self.write_varint(varint)?;
104 }
105 FieldValue::I32(bytes) => {
106 self.write_all(bytes)?;
107 bytes_written += 4;
108 }
109 FieldValue::I64(bytes) => {
110 self.write_all(bytes)?;
111 bytes_written += 8;
112 }
113 FieldValue::Len(data) => {
114 let data_slice = data.as_ref();
116 let length_varint = Varint::from_uint64(data_slice.len() as u64);
117 bytes_written += self.write_varint(&length_varint)?;
118 self.write_all(data_slice)?;
120 bytes_written += data_slice.len();
121 }
122 }
123
124 Ok(bytes_written)
125 }
126
127 fn write_protobuf_fields<'a, L: AsRef<[u8]> + 'a, I>(&mut self, fields: I) -> Result<usize>
128 where
129 I: IntoIterator<Item = &'a Field<L>>,
130 {
131 let mut total_bytes = 0;
132 for field in fields {
133 total_bytes += self.write_protobuf_field(field)?;
134 }
135 Ok(total_bytes)
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142 use crate::field_number::FieldNumber;
143
144 #[test]
145 fn test_write_single_varint_field() {
146 let mut buffer = Vec::new();
147
148 let field: Field<Vec<u8>> = Field::new(
149 FieldNumber::try_from(1).unwrap(),
150 FieldValue::from_uint64(150),
151 );
152
153 let bytes_written = buffer.write_protobuf_field(&field).unwrap();
154 assert_eq!(bytes_written, 3); assert_eq!(buffer, vec![0x08, 0x96, 0x01]); }
157
158 #[test]
159 fn test_write_len_field() {
160 let mut buffer = Vec::new();
161
162 let field: Field<Vec<u8>> = Field::new(
163 FieldNumber::try_from(2).unwrap(),
164 FieldValue::Len("Hel".to_string().into_bytes()),
165 );
166
167 buffer.write_protobuf_field(&field).unwrap();
168 assert_eq!(buffer, vec![0x12, 0x03, 0x48, 0x65, 0x6c]); }
170
171 #[test]
172 fn test_write_i32_field() {
173 let mut buffer = Vec::new();
174
175 let field: Field<Vec<u8>> = Field::new(
176 FieldNumber::try_from(2).unwrap(),
177 FieldValue::from_fixed32(0x12345678),
178 );
179
180 buffer.write_protobuf_field(&field).unwrap();
181 assert_eq!(buffer, vec![0x15, 0x78, 0x56, 0x34, 0x12]); }
183
184 #[test]
185 fn test_write_i64_field() {
186 let mut buffer = Vec::new();
187
188 let field: Field<Vec<u8>> = Field::new(
189 FieldNumber::try_from(3).unwrap(),
190 FieldValue::from_fixed64(0x1234567890ABCDEF),
191 );
192
193 buffer.write_protobuf_field(&field).unwrap();
194 assert_eq!(
195 buffer,
196 vec![0x19, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]
197 ); }
199
200 #[test]
201 fn test_write_multiple_fields() {
202 let mut buffer = Vec::new();
203
204 let fields: Vec<Field<Vec<u8>>> = vec![
205 Field::new(
206 FieldNumber::try_from(1).unwrap(),
207 FieldValue::from_uint64(150),
208 ),
209 Field::new(
210 FieldNumber::try_from(2).unwrap(),
211 FieldValue::Len("Hel".to_string().into_bytes()),
212 ),
213 ];
214
215 buffer.write_protobuf_fields(&fields).unwrap();
216 assert_eq!(
217 buffer,
218 vec![
219 0x08, 0x96, 0x01, 0x12, 0x03, 0x48, 0x65, 0x6c, ]
222 );
223 }
224
225 #[test]
226 fn test_field_encoded_size() {
227 let field: Field<Vec<u8>> = Field::new(
228 FieldNumber::try_from(1).unwrap(),
229 FieldValue::from_uint64(150),
230 );
231 assert_eq!(field.encoded_size(), 3); let field: Field<Vec<u8>> = Field::new(
234 FieldNumber::try_from(2).unwrap(),
235 FieldValue::Len("Hello".to_string().into_bytes()),
236 );
237 assert_eq!(field.encoded_size(), 7); }
239
240 #[test]
241 fn test_fieldvalue_constructors() {
242 assert!(matches!(
244 FieldValue::<Vec<u8>>::from_uint64(42),
245 FieldValue::Varint(_)
246 ));
247 assert!(matches!(
248 FieldValue::<Vec<u8>>::from_uint32(42),
249 FieldValue::Varint(_)
250 ));
251 assert!(matches!(
252 FieldValue::<Vec<u8>>::from_sint64(-42),
253 FieldValue::Varint(_)
254 ));
255 assert!(matches!(
256 FieldValue::<Vec<u8>>::from_sint32(-42),
257 FieldValue::Varint(_)
258 ));
259 assert!(matches!(
260 FieldValue::<Vec<u8>>::from_int64(-42),
261 FieldValue::Varint(_)
262 ));
263 assert!(matches!(
264 FieldValue::<Vec<u8>>::from_int32(-42),
265 FieldValue::Varint(_)
266 ));
267 assert!(matches!(
268 FieldValue::<Vec<u8>>::from_bool(true),
269 FieldValue::Varint(_)
270 ));
271
272 assert!(matches!(
274 FieldValue::<Vec<u8>>::from_fixed32(42),
275 FieldValue::I32(_)
276 ));
277 assert!(matches!(
278 FieldValue::<Vec<u8>>::from_sfixed32(-42),
279 FieldValue::I32(_)
280 ));
281 assert!(matches!(
282 FieldValue::<Vec<u8>>::from_float(3.14),
283 FieldValue::I32(_)
284 ));
285 assert!(matches!(
286 FieldValue::<Vec<u8>>::from_fixed64(42),
287 FieldValue::I64(_)
288 ));
289 assert!(matches!(
290 FieldValue::<Vec<u8>>::from_sfixed64(-42),
291 FieldValue::I64(_)
292 ));
293 assert!(matches!(
294 FieldValue::<Vec<u8>>::from_double(3.14),
295 FieldValue::I64(_)
296 ));
297
298 assert!(matches!(FieldValue::Len(vec![1, 2, 3]), FieldValue::Len(_)));
300 assert!(matches!(
301 FieldValue::Len("test".to_string().into_bytes()),
302 FieldValue::Len(_)
303 ));
304 }
305
306 #[cfg(feature = "read")]
308 mod roundtrip_tests {
309 use super::*;
310 use crate::field::read::ReadExtProtobuf;
311
312 #[test]
313 fn test_roundtrip_varint() {
314 let mut buffer = Vec::new();
315
316 let original_field: Field<Vec<u8>> = Field::new(
318 FieldNumber::try_from(1).unwrap(),
319 FieldValue::from_uint64(150),
320 );
321 buffer.write_protobuf_field(&original_field).unwrap();
322
323 let reader = buffer.as_slice();
325 let fields: Vec<_> = reader
326 .read_protobuf_fields()
327 .collect::<::std::result::Result<Vec<_>, _>>()
328 .unwrap();
329 assert_eq!(fields.len(), 1);
330 assert_eq!(fields[0], original_field);
331 }
332
333 #[test]
334 fn test_roundtrip_string() {
335 let mut buffer = Vec::new();
336
337 let original_field: Field<Vec<u8>> = Field::new(
339 FieldNumber::try_from(2).unwrap(),
340 FieldValue::Len("Hello, Protocol Buffers!".to_string().into_bytes()),
341 );
342 buffer.write_protobuf_field(&original_field).unwrap();
343
344 let reader = buffer.as_slice();
346 let fields: Vec<_> = reader
347 .read_protobuf_fields()
348 .collect::<::std::result::Result<Vec<_>, _>>()
349 .unwrap();
350 assert_eq!(fields.len(), 1);
351 let read_field = &fields[0];
352
353 assert_eq!(*read_field, original_field);
354 }
355
356 #[test]
357 fn test_roundtrip_multiple_fields() {
358 let mut buffer = Vec::new();
359
360 let original_fields: Vec<Field<Vec<u8>>> = vec![
362 Field::new(
363 FieldNumber::try_from(1).unwrap(),
364 FieldValue::from_uint64(150),
365 ),
366 Field::new(
367 FieldNumber::try_from(2).unwrap(),
368 FieldValue::Len("Hello".to_string().into_bytes()),
369 ),
370 Field::new(
371 FieldNumber::try_from(3).unwrap(),
372 FieldValue::from_fixed32(0x12345678),
373 ),
374 ];
375 buffer.write_protobuf_fields(&original_fields).unwrap();
376
377 let reader = buffer.as_slice();
379 let read_fields: Vec<_> = reader
380 .read_protobuf_fields()
381 .collect::<::std::result::Result<Vec<_>, _>>()
382 .unwrap();
383
384 assert_eq!(read_fields, original_fields);
385 }
386 }
387}