protobuf/
coded_output_stream.rs

1use std::io;
2use std::io::Write;
3use std::mem;
4use std::mem::MaybeUninit;
5use std::ptr;
6use std::slice;
7
8use crate::misc::maybe_uninit_write;
9use crate::misc::maybe_uninit_write_slice;
10use crate::misc::vec_spare_capacity_mut;
11use crate::varint;
12use crate::wire_format;
13use crate::zigzag::encode_zig_zag_32;
14use crate::zigzag::encode_zig_zag_64;
15use crate::Message;
16use crate::ProtobufEnum;
17use crate::ProtobufError;
18use crate::ProtobufResult;
19use crate::UnknownFields;
20use crate::UnknownValueRef;
21
22/// Equal to the default buffer size of `BufWriter`, so when
23/// `CodedOutputStream` wraps `BufWriter`, it often skips double buffering.
24const OUTPUT_STREAM_BUFFER_SIZE: usize = 8 * 1024;
25
26#[doc(hidden)]
27pub trait WithCodedOutputStream {
28    fn with_coded_output_stream<T, F>(self, cb: F) -> ProtobufResult<T>
29    where
30        F: FnOnce(&mut CodedOutputStream) -> ProtobufResult<T>;
31}
32
33impl<'a> WithCodedOutputStream for &'a mut (dyn Write + 'a) {
34    fn with_coded_output_stream<T, F>(self, cb: F) -> ProtobufResult<T>
35    where
36        F: FnOnce(&mut CodedOutputStream) -> ProtobufResult<T>,
37    {
38        let mut os = CodedOutputStream::new(self);
39        let r = cb(&mut os)?;
40        os.flush()?;
41        Ok(r)
42    }
43}
44
45impl<'a> WithCodedOutputStream for &'a mut Vec<u8> {
46    fn with_coded_output_stream<T, F>(mut self, cb: F) -> ProtobufResult<T>
47    where
48        F: FnOnce(&mut CodedOutputStream) -> ProtobufResult<T>,
49    {
50        let mut os = CodedOutputStream::vec(&mut self);
51        let r = cb(&mut os)?;
52        os.flush()?;
53        Ok(r)
54    }
55}
56
57#[doc(hidden)]
58pub fn with_coded_output_stream_to_bytes<F>(cb: F) -> ProtobufResult<Vec<u8>>
59where
60    F: FnOnce(&mut CodedOutputStream) -> ProtobufResult<()>,
61{
62    let mut v = Vec::new();
63    v.with_coded_output_stream(cb)?;
64    Ok(v)
65}
66
67/// Output buffer/writer for `CodedOutputStream`.
68enum OutputTarget<'a> {
69    Write(&'a mut dyn Write, Vec<u8>),
70    Vec(&'a mut Vec<u8>),
71    /// The buffer is passed as `&[u8]` to `CodedOutputStream` constructor
72    /// and immediately converted to `buffer` field of `CodedOutputStream`,
73    /// it is not needed to be stored here.
74    /// Lifetime parameter of `CodedOutputStream` guarantees the buffer is valid
75    /// during the lifetime of `CodedOutputStream`.
76    Bytes,
77}
78
79/// Buffered write with handy utilities
80pub struct CodedOutputStream<'a> {
81    target: OutputTarget<'a>,
82    // Actual buffer is owned by `OutputTarget`,
83    // and here we alias the buffer so access to the buffer is branchless:
84    // access does not require switch by actual target type: `&[], `Vec`, `Write` etc.
85    // We don't access the actual buffer in `OutputTarget` except when
86    // we initialize `buffer` field here.
87    buffer: *mut [MaybeUninit<u8>],
88    // within buffer
89    position: usize,
90}
91
92impl<'a> CodedOutputStream<'a> {
93    /// Construct from given `Write`.
94    ///
95    /// `CodedOutputStream` is buffered even if `Write` is not
96    pub fn new(writer: &'a mut dyn Write) -> CodedOutputStream<'a> {
97        let buffer_len = OUTPUT_STREAM_BUFFER_SIZE;
98
99        let mut buffer_storage = Vec::with_capacity(buffer_len);
100
101        // SAFETY: we are not using the `buffer_storage`
102        // except for initializing the `buffer` field.
103        // See `buffer` field documentation.
104        let buffer = vec_spare_capacity_mut(&mut buffer_storage);
105        let buffer: *mut [MaybeUninit<u8>] = buffer;
106
107        CodedOutputStream {
108            target: OutputTarget::Write(writer, buffer_storage),
109            buffer,
110            position: 0,
111        }
112    }
113
114    /// `CodedOutputStream` which writes directly to bytes.
115    ///
116    /// Attempt to write more than bytes capacity results in error.
117    pub fn bytes(bytes: &'a mut [u8]) -> CodedOutputStream<'a> {
118        // SAFETY: it is safe to cast from &mut [u8] to &mut [MaybeUninit<u8>].
119        let buffer =
120            ptr::slice_from_raw_parts_mut(bytes.as_mut_ptr() as *mut MaybeUninit<u8>, bytes.len());
121        CodedOutputStream {
122            target: OutputTarget::Bytes,
123            buffer,
124            position: 0,
125        }
126    }
127
128    /// `CodedOutputStream` which writes directly to `Vec<u8>`.
129    ///
130    /// Caller should call `flush` at the end to guarantee vec contains
131    /// all written data.
132    pub fn vec(vec: &'a mut Vec<u8>) -> CodedOutputStream<'a> {
133        let buffer: *mut [MaybeUninit<u8>] = &mut [];
134        CodedOutputStream {
135            target: OutputTarget::Vec(vec),
136            buffer,
137            position: 0,
138        }
139    }
140
141    /// Check if EOF is reached.
142    ///
143    /// # Panics
144    ///
145    /// If underlying write has no EOF
146    pub fn check_eof(&self) {
147        match self.target {
148            OutputTarget::Bytes => {
149                assert_eq!(self.buffer().len() as u64, self.position as u64);
150            }
151            OutputTarget::Write(..) | OutputTarget::Vec(..) => {
152                panic!("must not be called with Writer or Vec");
153            }
154        }
155    }
156
157    #[inline(always)]
158    fn buffer(&self) -> &[MaybeUninit<u8>] {
159        // SAFETY: see the `buffer` field documentation about invariants.
160        unsafe { &*(self.buffer as *mut [MaybeUninit<u8>]) }
161    }
162
163    #[inline(always)]
164    fn filled_buffer_impl<'s>(buffer: *mut [MaybeUninit<u8>], position: usize) -> &'s [u8] {
165        // SAFETY: this function is safe assuming `buffer` and `position`
166        //   are `self.buffer` and `safe.position`:
167        //   * `CodedOutputStream` has invariant that `position <= buffer.len()`.
168        //   * `buffer` is filled up to `position`.
169        unsafe { slice::from_raw_parts_mut(buffer as *mut u8, position) }
170    }
171
172    fn refresh_buffer(&mut self) -> ProtobufResult<()> {
173        match self.target {
174            OutputTarget::Write(ref mut write, _) => {
175                write.write_all(Self::filled_buffer_impl(self.buffer, self.position))?;
176                self.position = 0;
177            }
178            OutputTarget::Vec(ref mut vec) => unsafe {
179                let vec_len = vec.len();
180                assert!(vec_len + self.position <= vec.capacity());
181                vec.set_len(vec_len + self.position);
182                vec.reserve(1);
183                self.buffer = vec_spare_capacity_mut(vec);
184                self.position = 0;
185            },
186            OutputTarget::Bytes => {
187                return Err(ProtobufError::IoError(io::Error::new(
188                    io::ErrorKind::Other,
189                    "given slice is too small to serialize the message",
190                )));
191            }
192        }
193        Ok(())
194    }
195
196    /// Flush the buffer to underlying write
197    pub fn flush(&mut self) -> ProtobufResult<()> {
198        match self.target {
199            OutputTarget::Bytes => Ok(()),
200            OutputTarget::Write(..) | OutputTarget::Vec(..) => {
201                // TODO: must not reserve additional in Vec
202                self.refresh_buffer()
203            }
204        }
205    }
206
207    /// Write a byte
208    pub fn write_raw_byte(&mut self, byte: u8) -> ProtobufResult<()> {
209        if self.position as usize == self.buffer().len() {
210            self.refresh_buffer()?;
211        }
212        unsafe { maybe_uninit_write(&mut (&mut *self.buffer)[self.position as usize], byte) };
213        self.position += 1;
214        Ok(())
215    }
216
217    /// Write bytes
218    pub fn write_raw_bytes(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
219        if bytes.len() <= self.buffer().len() - self.position {
220            let bottom = self.position as usize;
221            let top = bottom + (bytes.len() as usize);
222            // SAFETY: see the `buffer` field documentation about invariants.
223            let buffer = unsafe { &mut (&mut *self.buffer)[bottom..top] };
224            maybe_uninit_write_slice(buffer, bytes);
225            self.position += bytes.len();
226            return Ok(());
227        }
228
229        self.refresh_buffer()?;
230
231        assert!(self.position == 0);
232
233        if self.position + bytes.len() < self.buffer().len() {
234            // SAFETY: see the `buffer` field documentation about invariants.
235            let buffer =
236                unsafe { &mut (&mut *self.buffer)[self.position..self.position + bytes.len()] };
237            maybe_uninit_write_slice(buffer, bytes);
238            self.position += bytes.len();
239            return Ok(());
240        }
241
242        match self.target {
243            OutputTarget::Bytes => {
244                unreachable!();
245            }
246            OutputTarget::Write(ref mut write, _) => {
247                write.write_all(bytes)?;
248            }
249            OutputTarget::Vec(ref mut vec) => {
250                vec.extend(bytes);
251                self.buffer = vec_spare_capacity_mut(vec)
252            }
253        }
254        Ok(())
255    }
256
257    /// Write a tag
258    pub fn write_tag(
259        &mut self,
260        field_number: u32,
261        wire_type: wire_format::WireType,
262    ) -> ProtobufResult<()> {
263        self.write_raw_varint32(wire_format::Tag::make(field_number, wire_type).value())
264    }
265
266    /// Write varint
267    pub fn write_raw_varint32(&mut self, value: u32) -> ProtobufResult<()> {
268        if self.buffer().len() - self.position >= 5 {
269            // fast path
270            let len = unsafe {
271                varint::encode_varint32(value, &mut (&mut *self.buffer)[self.position..])
272            };
273            self.position += len;
274            Ok(())
275        } else {
276            // slow path
277            let buf = &mut [0u8; 5];
278            let len = varint::encode_varint32(value, unsafe {
279                slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut MaybeUninit<u8>, buf.len())
280            });
281            self.write_raw_bytes(&buf[..len])
282        }
283    }
284
285    /// Write varint
286    pub fn write_raw_varint64(&mut self, value: u64) -> ProtobufResult<()> {
287        if self.buffer().len() - self.position >= 10 {
288            // fast path
289            let len = unsafe {
290                varint::encode_varint64(value, &mut (&mut *self.buffer)[self.position..])
291            };
292            self.position += len;
293            Ok(())
294        } else {
295            // slow path
296            let buf = &mut [0u8; 10];
297            let len = varint::encode_varint64(value, unsafe {
298                slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut MaybeUninit<u8>, buf.len())
299            });
300            self.write_raw_bytes(&buf[..len])
301        }
302    }
303
304    /// Write 32-bit integer little endian
305    pub fn write_raw_little_endian32(&mut self, value: u32) -> ProtobufResult<()> {
306        let bytes = unsafe { mem::transmute::<_, [u8; 4]>(value.to_le()) };
307        self.write_raw_bytes(&bytes)
308    }
309
310    /// Write 64-bit integer little endian
311    pub fn write_raw_little_endian64(&mut self, value: u64) -> ProtobufResult<()> {
312        let bytes = unsafe { mem::transmute::<_, [u8; 8]>(value.to_le()) };
313        self.write_raw_bytes(&bytes)
314    }
315
316    /// Write `float`
317    pub fn write_float_no_tag(&mut self, value: f32) -> ProtobufResult<()> {
318        let bits = unsafe { mem::transmute::<f32, u32>(value) };
319        self.write_raw_little_endian32(bits)
320    }
321
322    /// Write `double`
323    pub fn write_double_no_tag(&mut self, value: f64) -> ProtobufResult<()> {
324        let bits = unsafe { mem::transmute::<f64, u64>(value) };
325        self.write_raw_little_endian64(bits)
326    }
327
328    /// Write `float` field
329    pub fn write_float(&mut self, field_number: u32, value: f32) -> ProtobufResult<()> {
330        self.write_tag(field_number, wire_format::WireTypeFixed32)?;
331        self.write_float_no_tag(value)?;
332        Ok(())
333    }
334
335    /// Write `double` field
336    pub fn write_double(&mut self, field_number: u32, value: f64) -> ProtobufResult<()> {
337        self.write_tag(field_number, wire_format::WireTypeFixed64)?;
338        self.write_double_no_tag(value)?;
339        Ok(())
340    }
341
342    /// Write varint
343    pub fn write_uint64_no_tag(&mut self, value: u64) -> ProtobufResult<()> {
344        self.write_raw_varint64(value)
345    }
346
347    /// Write varint
348    pub fn write_uint32_no_tag(&mut self, value: u32) -> ProtobufResult<()> {
349        self.write_raw_varint32(value)
350    }
351
352    /// Write varint
353    pub fn write_int64_no_tag(&mut self, value: i64) -> ProtobufResult<()> {
354        self.write_raw_varint64(value as u64)
355    }
356
357    /// Write varint
358    pub fn write_int32_no_tag(&mut self, value: i32) -> ProtobufResult<()> {
359        self.write_raw_varint64(value as u64)
360    }
361
362    /// Write zigzag varint
363    pub fn write_sint64_no_tag(&mut self, value: i64) -> ProtobufResult<()> {
364        self.write_uint64_no_tag(encode_zig_zag_64(value))
365    }
366
367    /// Write zigzag varint
368    pub fn write_sint32_no_tag(&mut self, value: i32) -> ProtobufResult<()> {
369        self.write_uint32_no_tag(encode_zig_zag_32(value))
370    }
371
372    /// Write `fixed64`
373    pub fn write_fixed64_no_tag(&mut self, value: u64) -> ProtobufResult<()> {
374        self.write_raw_little_endian64(value)
375    }
376
377    /// Write `fixed32`
378    pub fn write_fixed32_no_tag(&mut self, value: u32) -> ProtobufResult<()> {
379        self.write_raw_little_endian32(value)
380    }
381
382    /// Write `sfixed64`
383    pub fn write_sfixed64_no_tag(&mut self, value: i64) -> ProtobufResult<()> {
384        self.write_raw_little_endian64(value as u64)
385    }
386
387    /// Write `sfixed32`
388    pub fn write_sfixed32_no_tag(&mut self, value: i32) -> ProtobufResult<()> {
389        self.write_raw_little_endian32(value as u32)
390    }
391
392    /// Write `bool`
393    pub fn write_bool_no_tag(&mut self, value: bool) -> ProtobufResult<()> {
394        self.write_raw_varint32(if value { 1 } else { 0 })
395    }
396
397    /// Write `enum`
398    pub fn write_enum_no_tag(&mut self, value: i32) -> ProtobufResult<()> {
399        self.write_int32_no_tag(value)
400    }
401
402    /// Write `enum`
403    pub fn write_enum_obj_no_tag<E>(&mut self, value: E) -> ProtobufResult<()>
404    where
405        E: ProtobufEnum,
406    {
407        self.write_enum_no_tag(value.value())
408    }
409
410    /// Write unknown value
411    pub fn write_unknown_no_tag(&mut self, unknown: UnknownValueRef) -> ProtobufResult<()> {
412        match unknown {
413            UnknownValueRef::Fixed64(fixed64) => self.write_raw_little_endian64(fixed64),
414            UnknownValueRef::Fixed32(fixed32) => self.write_raw_little_endian32(fixed32),
415            UnknownValueRef::Varint(varint) => self.write_raw_varint64(varint),
416            UnknownValueRef::LengthDelimited(bytes) => self.write_bytes_no_tag(bytes),
417        }
418    }
419
420    /// Write `uint64` field
421    pub fn write_uint64(&mut self, field_number: u32, value: u64) -> ProtobufResult<()> {
422        self.write_tag(field_number, wire_format::WireTypeVarint)?;
423        self.write_uint64_no_tag(value)?;
424        Ok(())
425    }
426
427    /// Write `uint32` field
428    pub fn write_uint32(&mut self, field_number: u32, value: u32) -> ProtobufResult<()> {
429        self.write_tag(field_number, wire_format::WireTypeVarint)?;
430        self.write_uint32_no_tag(value)?;
431        Ok(())
432    }
433
434    /// Write `int64` field
435    pub fn write_int64(&mut self, field_number: u32, value: i64) -> ProtobufResult<()> {
436        self.write_tag(field_number, wire_format::WireTypeVarint)?;
437        self.write_int64_no_tag(value)?;
438        Ok(())
439    }
440
441    /// Write `int32` field
442    pub fn write_int32(&mut self, field_number: u32, value: i32) -> ProtobufResult<()> {
443        self.write_tag(field_number, wire_format::WireTypeVarint)?;
444        self.write_int32_no_tag(value)?;
445        Ok(())
446    }
447
448    /// Write `sint64` field
449    pub fn write_sint64(&mut self, field_number: u32, value: i64) -> ProtobufResult<()> {
450        self.write_tag(field_number, wire_format::WireTypeVarint)?;
451        self.write_sint64_no_tag(value)?;
452        Ok(())
453    }
454
455    /// Write `sint32` field
456    pub fn write_sint32(&mut self, field_number: u32, value: i32) -> ProtobufResult<()> {
457        self.write_tag(field_number, wire_format::WireTypeVarint)?;
458        self.write_sint32_no_tag(value)?;
459        Ok(())
460    }
461
462    /// Write `fixed64` field
463    pub fn write_fixed64(&mut self, field_number: u32, value: u64) -> ProtobufResult<()> {
464        self.write_tag(field_number, wire_format::WireTypeFixed64)?;
465        self.write_fixed64_no_tag(value)?;
466        Ok(())
467    }
468
469    /// Write `fixed32` field
470    pub fn write_fixed32(&mut self, field_number: u32, value: u32) -> ProtobufResult<()> {
471        self.write_tag(field_number, wire_format::WireTypeFixed32)?;
472        self.write_fixed32_no_tag(value)?;
473        Ok(())
474    }
475
476    /// Write `sfixed64` field
477    pub fn write_sfixed64(&mut self, field_number: u32, value: i64) -> ProtobufResult<()> {
478        self.write_tag(field_number, wire_format::WireTypeFixed64)?;
479        self.write_sfixed64_no_tag(value)?;
480        Ok(())
481    }
482
483    /// Write `sfixed32` field
484    pub fn write_sfixed32(&mut self, field_number: u32, value: i32) -> ProtobufResult<()> {
485        self.write_tag(field_number, wire_format::WireTypeFixed32)?;
486        self.write_sfixed32_no_tag(value)?;
487        Ok(())
488    }
489
490    /// Write `bool` field
491    pub fn write_bool(&mut self, field_number: u32, value: bool) -> ProtobufResult<()> {
492        self.write_tag(field_number, wire_format::WireTypeVarint)?;
493        self.write_bool_no_tag(value)?;
494        Ok(())
495    }
496
497    /// Write `enum` field
498    pub fn write_enum(&mut self, field_number: u32, value: i32) -> ProtobufResult<()> {
499        self.write_tag(field_number, wire_format::WireTypeVarint)?;
500        self.write_enum_no_tag(value)?;
501        Ok(())
502    }
503
504    /// Write `enum` field
505    pub fn write_enum_obj<E>(&mut self, field_number: u32, value: E) -> ProtobufResult<()>
506    where
507        E: ProtobufEnum,
508    {
509        self.write_enum(field_number, value.value())
510    }
511
512    /// Write unknown field
513    pub fn write_unknown(
514        &mut self,
515        field_number: u32,
516        value: UnknownValueRef,
517    ) -> ProtobufResult<()> {
518        self.write_tag(field_number, value.wire_type())?;
519        self.write_unknown_no_tag(value)?;
520        Ok(())
521    }
522
523    /// Write unknown fields
524    pub fn write_unknown_fields(&mut self, fields: &UnknownFields) -> ProtobufResult<()> {
525        for (number, values) in fields {
526            for value in values {
527                self.write_unknown(number, value)?;
528            }
529        }
530        Ok(())
531    }
532
533    /// Write bytes
534    pub fn write_bytes_no_tag(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
535        self.write_raw_varint32(bytes.len() as u32)?;
536        self.write_raw_bytes(bytes)?;
537        Ok(())
538    }
539
540    /// Write string
541    pub fn write_string_no_tag(&mut self, s: &str) -> ProtobufResult<()> {
542        self.write_bytes_no_tag(s.as_bytes())
543    }
544
545    /// Write message
546    pub fn write_message_no_tag<M: Message>(&mut self, msg: &M) -> ProtobufResult<()> {
547        msg.write_length_delimited_to(self)
548    }
549
550    /// Write `bytes` field
551    pub fn write_bytes(&mut self, field_number: u32, bytes: &[u8]) -> ProtobufResult<()> {
552        self.write_tag(field_number, wire_format::WireTypeLengthDelimited)?;
553        self.write_bytes_no_tag(bytes)?;
554        Ok(())
555    }
556
557    /// Write `string` field
558    pub fn write_string(&mut self, field_number: u32, s: &str) -> ProtobufResult<()> {
559        self.write_tag(field_number, wire_format::WireTypeLengthDelimited)?;
560        self.write_string_no_tag(s)?;
561        Ok(())
562    }
563
564    /// Write `message` field
565    pub fn write_message<M: Message>(&mut self, field_number: u32, msg: &M) -> ProtobufResult<()> {
566        self.write_tag(field_number, wire_format::WireTypeLengthDelimited)?;
567        self.write_message_no_tag(msg)?;
568        Ok(())
569    }
570}
571
572impl<'a> Write for CodedOutputStream<'a> {
573    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
574        self.write_raw_bytes(buf)?;
575        Ok(buf.len())
576    }
577
578    fn flush(&mut self) -> io::Result<()> {
579        CodedOutputStream::flush(self).map_err(Into::into)
580    }
581}
582
583#[cfg(test)]
584mod test {
585    use std::io::Write;
586    use std::iter;
587
588    use crate::coded_output_stream::CodedOutputStream;
589    use crate::hex::decode_hex;
590    use crate::hex::encode_hex;
591    use crate::wire_format;
592    use crate::ProtobufResult;
593
594    fn test_write<F>(expected: &str, mut gen: F)
595    where
596        F: FnMut(&mut CodedOutputStream) -> ProtobufResult<()>,
597    {
598        let expected_bytes = decode_hex(expected);
599
600        // write to Write
601        {
602            let mut v = Vec::new();
603            {
604                let mut os = CodedOutputStream::new(&mut v as &mut dyn Write);
605                gen(&mut os).unwrap();
606                os.flush().unwrap();
607            }
608            assert_eq!(encode_hex(&expected_bytes), encode_hex(&v));
609        }
610
611        // write to &[u8]
612        {
613            let mut r = Vec::with_capacity(expected_bytes.len());
614            r.resize(expected_bytes.len(), 0);
615            {
616                let mut os = CodedOutputStream::bytes(&mut r);
617                gen(&mut os).unwrap();
618                os.check_eof();
619            }
620            assert_eq!(encode_hex(&expected_bytes), encode_hex(&r));
621        }
622
623        // write to Vec<u8>
624        {
625            let mut r = Vec::new();
626            r.extend(&[11, 22, 33, 44, 55, 66, 77]);
627            {
628                let mut os = CodedOutputStream::vec(&mut r);
629                gen(&mut os).unwrap();
630                os.flush().unwrap();
631            }
632
633            r.drain(..7);
634            assert_eq!(encode_hex(&expected_bytes), encode_hex(&r));
635        }
636    }
637
638    #[test]
639    fn test_output_stream_write_raw_byte() {
640        test_write("a1", |os| os.write_raw_byte(0xa1));
641    }
642
643    #[test]
644    fn test_output_stream_write_tag() {
645        test_write("08", |os| os.write_tag(1, wire_format::WireTypeVarint));
646    }
647
648    #[test]
649    fn test_output_stream_write_raw_bytes() {
650        test_write("00 ab", |os| os.write_raw_bytes(&[0x00, 0xab]));
651
652        let expected = iter::repeat("01 02 03 04")
653            .take(2048)
654            .collect::<Vec<_>>()
655            .join(" ");
656        test_write(&expected, |os| {
657            for _ in 0..2048 {
658                os.write_raw_bytes(&[0x01, 0x02, 0x03, 0x04])?;
659            }
660
661            Ok(())
662        });
663    }
664
665    #[test]
666    fn test_output_stream_write_raw_varint32() {
667        test_write("96 01", |os| os.write_raw_varint32(150));
668        test_write("ff ff ff ff 0f", |os| os.write_raw_varint32(0xffffffff));
669    }
670
671    #[test]
672    fn test_output_stream_write_raw_varint64() {
673        test_write("96 01", |os| os.write_raw_varint64(150));
674        test_write("ff ff ff ff ff ff ff ff ff 01", |os| {
675            os.write_raw_varint64(0xffffffffffffffff)
676        });
677    }
678
679    #[test]
680    fn test_output_stream_write_int32_no_tag() {
681        test_write("ff ff ff ff ff ff ff ff ff 01", |os| {
682            os.write_int32_no_tag(-1)
683        });
684    }
685
686    #[test]
687    fn test_output_stream_write_int64_no_tag() {
688        test_write("ff ff ff ff ff ff ff ff ff 01", |os| {
689            os.write_int64_no_tag(-1)
690        });
691    }
692
693    #[test]
694    fn test_output_stream_write_raw_little_endian32() {
695        test_write("f1 e2 d3 c4", |os| os.write_raw_little_endian32(0xc4d3e2f1));
696    }
697
698    #[test]
699    fn test_output_stream_write_float_no_tag() {
700        test_write("95 73 13 61", |os| os.write_float_no_tag(17e19));
701    }
702
703    #[test]
704    fn test_output_stream_write_double_no_tag() {
705        test_write("40 d5 ab 68 b3 07 3d 46", |os| {
706            os.write_double_no_tag(23e29)
707        });
708    }
709
710    #[test]
711    fn test_output_stream_write_raw_little_endian64() {
712        test_write("f1 e2 d3 c4 b5 a6 07 f8", |os| {
713            os.write_raw_little_endian64(0xf807a6b5c4d3e2f1)
714        });
715    }
716
717    #[test]
718    fn test_output_stream_io_write() {
719        let expected = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77];
720
721        // write to Write
722        {
723            let mut v = Vec::new();
724            {
725                let mut os = CodedOutputStream::new(&mut v as &mut dyn Write);
726                Write::write(&mut os, &expected).expect("io::Write::write");
727                Write::flush(&mut os).expect("io::Write::flush");
728            }
729            assert_eq!(expected, *v);
730        }
731
732        // write to &[u8]
733        {
734            let mut v = Vec::with_capacity(expected.len());
735            v.resize(expected.len(), 0);
736            {
737                let mut os = CodedOutputStream::bytes(&mut v);
738                Write::write(&mut os, &expected).expect("io::Write::write");
739                Write::flush(&mut os).expect("io::Write::flush");
740                os.check_eof();
741            }
742            assert_eq!(expected, *v);
743        }
744
745        // write to Vec<u8>
746        {
747            let mut v = Vec::new();
748            {
749                let mut os = CodedOutputStream::vec(&mut v);
750                Write::write(&mut os, &expected).expect("io::Write::write");
751                Write::flush(&mut os).expect("io::Write::flush");
752            }
753            assert_eq!(expected, *v);
754        }
755    }
756}