winter_utils/serde/
byte_writer.rs

1// Copyright (c) Facebook, Inc. and its affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6use super::Serializable;
7
8// BYTE WRITER TRAIT
9// ================================================================================================
10
11/// Defines how primitive values are to be written into `Self`.
12pub trait ByteWriter: Sized {
13    // REQUIRED METHODS
14    // --------------------------------------------------------------------------------------------
15
16    /// Writes a single byte into `self`.
17    ///
18    /// # Panics
19    /// Panics if the byte could not be written into `self`.
20    fn write_u8(&mut self, value: u8);
21
22    /// Writes a sequence of bytes into `self`.
23    ///
24    /// # Panics
25    /// Panics if the sequence of bytes could not be written into `self`.
26    fn write_bytes(&mut self, values: &[u8]);
27
28    // PROVIDED METHODS
29    // --------------------------------------------------------------------------------------------
30
31    /// Writes a boolean value into `self`.
32    ///
33    /// A boolean value is written as a single byte.
34    ///
35    /// # Panics
36    /// Panics if the value could not be written into `self`.
37    fn write_bool(&mut self, val: bool) {
38        self.write_u8(val as u8);
39    }
40
41    /// Writes a u16 value in little-endian byte order into `self`.
42    ///
43    /// # Panics
44    /// Panics if the value could not be written into `self`.
45    fn write_u16(&mut self, value: u16) {
46        self.write_bytes(&value.to_le_bytes());
47    }
48
49    /// Writes a u32 value in little-endian byte order into `self`.
50    ///
51    /// # Panics
52    /// Panics if the value could not be written into `self`.
53    fn write_u32(&mut self, value: u32) {
54        self.write_bytes(&value.to_le_bytes());
55    }
56
57    /// Writes a u64 value in little-endian byte order into `self`.
58    ///
59    /// # Panics
60    /// Panics if the value could not be written into `self`.
61    fn write_u64(&mut self, value: u64) {
62        self.write_bytes(&value.to_le_bytes());
63    }
64
65    /// Writes a u128 value in little-endian byte order into `self`.
66    ///
67    /// # Panics
68    /// Panics if the value could not be written into `self`.
69    fn write_u128(&mut self, value: u128) {
70        self.write_bytes(&value.to_le_bytes());
71    }
72
73    /// Writes a usize value in [vint64](https://docs.rs/vint64/latest/vint64/) format into `self`.
74    ///
75    /// # Panics
76    /// Panics if the value could not be written into `self`.
77    fn write_usize(&mut self, value: usize) {
78        // convert the value into a u64 so that we always get 8 bytes from to_le_bytes() call
79        let value = value as u64;
80        let length = usize_encoded_len(value);
81
82        // 9-byte special case
83        if length == 9 {
84            // length byte is zero in this case
85            self.write_u8(0);
86            self.write(value.to_le_bytes());
87        } else {
88            let encoded_bytes = (((value << 1) | 1) << (length - 1)).to_le_bytes();
89            self.write_bytes(&encoded_bytes[..length]);
90        }
91    }
92
93    /// Writes a serializable value into `self`.
94    ///
95    /// # Panics
96    /// Panics if the value could not be written into `self`.
97    fn write<S: Serializable>(&mut self, value: S) {
98        value.write_into(self)
99    }
100
101    /// Serializes all `elements` and writes the resulting bytes into `self`.
102    ///
103    /// This method does not write any metadata (e.g. number of serialized elements) into `self`.
104    fn write_many<S, T>(&mut self, elements: T)
105    where
106        T: IntoIterator<Item = S>,
107        S: Serializable,
108    {
109        for element in elements {
110            element.write_into(self);
111        }
112    }
113}
114
115// BYTE WRITER IMPLEMENTATIONS
116// ================================================================================================
117
118#[cfg(feature = "std")]
119impl<W: std::io::Write> ByteWriter for W {
120    #[inline(always)]
121    fn write_u8(&mut self, byte: u8) {
122        <W as std::io::Write>::write_all(self, &[byte]).expect("write failed")
123    }
124    #[inline(always)]
125    fn write_bytes(&mut self, bytes: &[u8]) {
126        <W as std::io::Write>::write_all(self, bytes).expect("write failed")
127    }
128}
129
130#[cfg(not(feature = "std"))]
131impl ByteWriter for alloc::vec::Vec<u8> {
132    fn write_u8(&mut self, value: u8) {
133        self.push(value);
134    }
135
136    fn write_bytes(&mut self, values: &[u8]) {
137        self.extend_from_slice(values);
138    }
139}
140
141// HELPER FUNCTIONS
142// ================================================================================================
143
144/// Returns the length of the usize value in vint64 encoding.
145pub(super) fn usize_encoded_len(value: u64) -> usize {
146    let zeros = value.leading_zeros() as usize;
147    let len = zeros.saturating_sub(1) / 7;
148    9 - core::cmp::min(len, 8)
149}
150
151#[cfg(all(test, feature = "std"))]
152mod tests {
153    use std::io::Cursor;
154
155    use super::*;
156
157    #[test]
158    fn write_adapter_passthrough() {
159        let mut writer = Cursor::new([0u8; 128]);
160        writer.write_bytes(b"nope");
161        let buf = writer.get_ref();
162        assert_eq!(&buf[..4], b"nope");
163    }
164
165    #[test]
166    #[should_panic]
167    fn write_adapter_writer_out_of_capacity() {
168        let mut writer = Cursor::new([0; 2]);
169        writer.write_bytes(b"nope");
170    }
171}