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(&mut self, field: &Field) -> Result<usize>;
54
55 fn write_protobuf_fields<'a, I>(&mut self, fields: I) -> Result<usize>
77 where
78 I: IntoIterator<Item = &'a Field>;
79}
80
81impl<W> WriteExtProtobuf for W
82where
83 W: Write,
84{
85 fn write_protobuf_field(&mut self, field: &Field) -> Result<usize> {
86 let mut bytes_written = 0;
87
88 let wire_type = match &field.value {
90 FieldValue::Varint(_) => WireType::Varint,
91 FieldValue::I32(_) => WireType::Int32,
92 FieldValue::I64(_) => WireType::Int64,
93 FieldValue::Len(_) => WireType::Len,
94 };
95 let tag = Tag {
96 field_number: field.field_number,
97 wire_type,
98 };
99 let tag_varint = tag.to_encoded();
100 bytes_written += self.write_varint(&tag_varint)?;
101
102 match &field.value {
104 FieldValue::Varint(varint) => {
105 bytes_written += self.write_varint(varint)?;
106 }
107 FieldValue::I32(bytes) => {
108 self.write_all(bytes)?;
109 bytes_written += 4;
110 }
111 FieldValue::I64(bytes) => {
112 self.write_all(bytes)?;
113 bytes_written += 8;
114 }
115 FieldValue::Len(data) => {
116 let length_varint = Varint::from_uint64(data.len() as u64);
118 bytes_written += self.write_varint(&length_varint)?;
119 self.write_all(data)?;
121 bytes_written += data.len();
122 }
123 }
124
125 Ok(bytes_written)
126 }
127
128 fn write_protobuf_fields<'a, I>(&mut self, fields: I) -> Result<usize>
129 where
130 I: IntoIterator<Item = &'a Field>,
131 {
132 let mut total_bytes = 0;
133 for field in fields {
134 total_bytes += self.write_protobuf_field(field)?;
135 }
136 Ok(total_bytes)
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143 use crate::field_number::FieldNumber;
144
145 #[test]
146 fn test_write_single_varint_field() {
147 let mut buffer = Vec::new();
148
149 let field = Field::new(
150 FieldNumber::try_from(1).unwrap(),
151 FieldValue::from_uint64(150),
152 );
153
154 let bytes_written = buffer.write_protobuf_field(&field).unwrap();
155 assert_eq!(bytes_written, 3); assert_eq!(buffer, vec![0x08, 0x96, 0x01]); }
158
159 #[test]
160 fn test_write_len_field() {
161 let mut buffer = Vec::new();
162
163 let field = Field::new(
164 FieldNumber::try_from(2).unwrap(),
165 FieldValue::from_string("Hel".to_string()),
166 );
167
168 buffer.write_protobuf_field(&field).unwrap();
169 assert_eq!(buffer, vec![0x12, 0x03, 0x48, 0x65, 0x6c]); }
171
172 #[test]
173 fn test_write_i32_field() {
174 let mut buffer = Vec::new();
175
176 let field = Field::new(
177 FieldNumber::try_from(2).unwrap(),
178 FieldValue::from_fixed32(0x12345678),
179 );
180
181 buffer.write_protobuf_field(&field).unwrap();
182 assert_eq!(buffer, vec![0x15, 0x78, 0x56, 0x34, 0x12]); }
184
185 #[test]
186 fn test_write_i64_field() {
187 let mut buffer = Vec::new();
188
189 let field = Field::new(
190 FieldNumber::try_from(3).unwrap(),
191 FieldValue::from_fixed64(0x1234567890ABCDEF),
192 );
193
194 buffer.write_protobuf_field(&field).unwrap();
195 assert_eq!(
196 buffer,
197 vec![0x19, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]
198 ); }
200
201 #[test]
202 fn test_write_multiple_fields() {
203 let mut buffer = Vec::new();
204
205 let fields = vec![
206 Field::new(
207 FieldNumber::try_from(1).unwrap(),
208 FieldValue::from_uint64(150),
209 ),
210 Field::new(
211 FieldNumber::try_from(2).unwrap(),
212 FieldValue::from_string("Hel".to_string()),
213 ),
214 ];
215
216 buffer.write_protobuf_fields(&fields).unwrap();
217 assert_eq!(
218 buffer,
219 vec![
220 0x08, 0x96, 0x01, 0x12, 0x03, 0x48, 0x65, 0x6c, ]
223 );
224 }
225
226 #[test]
227 fn test_field_encoded_size() {
228 let field = Field::new(
229 FieldNumber::try_from(1).unwrap(),
230 FieldValue::from_uint64(150),
231 );
232 assert_eq!(field.encoded_size(), 3); let field = Field::new(
235 FieldNumber::try_from(2).unwrap(),
236 FieldValue::from_string("Hello".to_string()),
237 );
238 assert_eq!(field.encoded_size(), 7); }
240
241 #[test]
242 fn test_fieldvalue_constructors() {
243 assert!(matches!(FieldValue::from_uint64(42), FieldValue::Varint(_)));
245 assert!(matches!(FieldValue::from_uint32(42), FieldValue::Varint(_)));
246 assert!(matches!(
247 FieldValue::from_sint64(-42),
248 FieldValue::Varint(_)
249 ));
250 assert!(matches!(
251 FieldValue::from_sint32(-42),
252 FieldValue::Varint(_)
253 ));
254 assert!(matches!(FieldValue::from_int64(-42), FieldValue::Varint(_)));
255 assert!(matches!(FieldValue::from_int32(-42), FieldValue::Varint(_)));
256 assert!(matches!(FieldValue::from_bool(true), FieldValue::Varint(_)));
257
258 assert!(matches!(FieldValue::from_fixed32(42), FieldValue::I32(_)));
260 assert!(matches!(FieldValue::from_sfixed32(-42), FieldValue::I32(_)));
261 assert!(matches!(FieldValue::from_float(3.14), FieldValue::I32(_)));
262 assert!(matches!(FieldValue::from_fixed64(42), FieldValue::I64(_)));
263 assert!(matches!(FieldValue::from_sfixed64(-42), FieldValue::I64(_)));
264 assert!(matches!(FieldValue::from_double(3.14), FieldValue::I64(_)));
265
266 assert!(matches!(
268 FieldValue::from_bytes(vec![1, 2, 3]),
269 FieldValue::Len(_)
270 ));
271 assert!(matches!(
272 FieldValue::from_string("test".to_string()),
273 FieldValue::Len(_)
274 ));
275 }
276
277 #[cfg(feature = "read")]
279 mod roundtrip_tests {
280 use super::*;
281 use crate::field::read::ReadExtProtobuf;
282
283 #[test]
284 fn test_roundtrip_varint() {
285 let mut buffer = Vec::new();
286
287 let original_field = Field::new(
289 FieldNumber::try_from(1).unwrap(),
290 FieldValue::from_uint64(150),
291 );
292 buffer.write_protobuf_field(&original_field).unwrap();
293
294 let mut reader = buffer.as_slice();
296 let read_field = reader.read_protobuf_field().unwrap().unwrap();
297
298 assert_eq!(read_field, original_field);
299 }
300
301 #[test]
302 fn test_roundtrip_string() {
303 let mut buffer = Vec::new();
304
305 let original_field = Field::new(
307 FieldNumber::try_from(2).unwrap(),
308 FieldValue::from_string("Hello, Protocol Buffers!".to_string()),
309 );
310 buffer.write_protobuf_field(&original_field).unwrap();
311
312 let mut reader = buffer.as_slice();
314 let read_field = reader.read_protobuf_field().unwrap().unwrap();
315
316 assert_eq!(read_field, original_field);
317 }
318
319 #[test]
320 fn test_roundtrip_multiple_fields() {
321 let mut buffer = Vec::new();
322
323 let original_fields = vec![
325 Field::new(
326 FieldNumber::try_from(1).unwrap(),
327 FieldValue::from_uint64(150),
328 ),
329 Field::new(
330 FieldNumber::try_from(2).unwrap(),
331 FieldValue::from_string("Hello".to_string()),
332 ),
333 Field::new(
334 FieldNumber::try_from(3).unwrap(),
335 FieldValue::from_fixed32(0x12345678),
336 ),
337 ];
338 buffer.write_protobuf_fields(&original_fields).unwrap();
339
340 let reader = buffer.as_slice();
342 let read_fields: Vec<_> = reader
343 .read_protobuf_fields()
344 .collect::<std::result::Result<Vec<_>, _>>()
345 .unwrap();
346
347 assert_eq!(read_fields, original_fields);
348 }
349 }
350}