Skip to main content

substrate_data/wire/frame/
packer.rs

1//! [`Packer`]: writes a frame.
2
3use super::sizes::{LENGTH_RESERVED, ONE_BYTE_MAX, VARINT_MAX_BYTES};
4use super::{floats, lanes};
5use crate::binary::table::interner::Interner;
6use crate::binary::writer::START_BYTES;
7use crate::binary::{Writer, varint, zigzag};
8use crate::schema::Schema;
9
10/// `v` as a frame.
11pub fn to_frame<T: Schema>(v: &T) -> Vec<u8> {
12    let mut p = Packer::new();
13    v.pack(&mut p);
14    p.finish()
15}
16
17/// Writes a frame.
18#[derive(Debug)]
19pub struct Packer {
20    out: Vec<u8>,
21    table: Vec<u8>,
22    strings: Interner,
23}
24
25impl Default for Packer {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl Packer {
32    /// An empty packer.
33    #[must_use]
34    pub fn new() -> Self {
35        Packer {
36            out: Vec::with_capacity(START_BYTES),
37            table: Vec::new(),
38            strings: Interner::new(),
39        }
40    }
41
42    /// An unsigned number (a count, an index).
43    pub fn put_u(&mut self, n: u64) {
44        varint(&mut self.out, n);
45    }
46
47    /// A signed number, zigzagged.
48    pub fn put_i(&mut self, n: i64) {
49        varint(&mut self.out, zigzag(n));
50    }
51
52    /// A bool, a byte.
53    pub fn put_bool(&mut self, b: bool) {
54        self.out.push(u8::from(b));
55    }
56
57    /// An `f64`, raw.
58    pub fn put_f64(&mut self, f: f64) {
59        self.out.extend_from_slice(&f.to_le_bytes());
60    }
61
62    /// An `f32`, raw.
63    pub fn put_f32(&mut self, f: f32) {
64        self.out.extend_from_slice(&f.to_le_bytes());
65    }
66
67    /// Floats, raw: a count, whether they're kept as `f32` (when every one
68    /// is one exactly — half the bytes), then each one's bytes.
69    pub fn put_f64s(&mut self, items: &[f64]) {
70        self.put_u(items.len() as u64);
71        let narrow = floats::fits_f32(items);
72        self.put_bool(narrow);
73        if narrow {
74            floats::put_narrow(&mut self.out, items);
75        } else {
76            floats::put_wide(&mut self.out, items);
77        }
78    }
79
80    /// Unsigned numbers bit-packed: a count, how many bits each takes (the
81    /// biggest one's, one at least), then the bits ([`lanes`]).
82    pub fn put_uints(&mut self, len: usize, items: impl Iterator<Item = u64> + Clone) {
83        self.put_u(len as u64);
84        let max = items.clone().fold(0, u64::max);
85        let bits = (u64::BITS - max.leading_zeros()).max(1);
86        self.out.push(u8::try_from(bits).unwrap_or(u8::MAX));
87        lanes::pack(&mut self.out, len, bits, items);
88    }
89
90    /// `f32`s, raw: a count, then each one's bytes.
91    pub fn put_f32s(&mut self, items: &[f32]) {
92        self.put_u(items.len() as u64);
93        floats::put_f32s(&mut self.out, items);
94    }
95
96    /// A string: its index in the table, which gets it the first time.
97    pub fn put_str(&mut self, s: &str) {
98        let i = match self.strings.lookup(&self.table, s) {
99            Ok(i) => i,
100            Err(hash) => {
101                varint(&mut self.table, s.len() as u64);
102                let at = self.table.len();
103                self.table.extend_from_slice(s.as_bytes());
104                self.strings.add(&self.table, s, at, hash)
105            }
106        };
107        self.put_u(i as u64);
108    }
109
110    /// Bytes: their count, then them.
111    pub fn put_bytes(&mut self, b: &[u8]) {
112        self.put_u(b.len() as u64);
113        self.out.extend_from_slice(b);
114    }
115
116    /// `v` in its binary form, as bytes: what a frame holds of a type that
117    /// doesn't pack itself.
118    pub fn put_tagged<T: Schema>(&mut self, v: &T) {
119        let mut w = Writer::body();
120        v.encode(&mut w);
121        self.put_bytes(&w.finish());
122    }
123
124    /// A record starts: where its length goes ([`Packer::end`] fills it in).
125    pub fn begin(&mut self) -> usize {
126        let at = self.out.len();
127        self.out.extend_from_slice(&[0; LENGTH_RESERVED]);
128        at
129    }
130
131    /// A list of `len` items packed one by one: its count, then its length
132    /// in bytes like a record's ([`Packer::end`] writes it), so a reader
133    /// can step over it.
134    pub fn begin_list(&mut self, len: usize) -> usize {
135        self.put_u(len as u64);
136        self.begin()
137    }
138
139    /// The record (or list) begun at `at` ends: its length written.
140    pub fn end(&mut self, at: usize) {
141        let len = self.out.len() - at - LENGTH_RESERVED;
142        if let Ok(byte) = u8::try_from(len)
143            && len <= ONE_BYTE_MAX
144        {
145            self.out[at] = byte;
146            return;
147        }
148        // The varint written at the end, then moved into place from the
149        // stack: a long record's length costs no allocation.
150        let end = self.out.len();
151        varint(&mut self.out, len as u64);
152        let mut length = [0; VARINT_MAX_BYTES];
153        let used = self.out.len() - end;
154        length[..used].copy_from_slice(&self.out[end..]);
155        self.out.truncate(end);
156        self.out.splice(at..=at, length[..used].iter().copied());
157    }
158
159    /// The frame: its body, its strings, their length backwards.
160    #[must_use]
161    pub fn finish(mut self) -> Vec<u8> {
162        self.seal();
163        self.out
164    }
165
166    /// The table and its length put after the body: `out` is the frame.
167    fn seal(&mut self) {
168        let table_len = self.table.len();
169        self.out.extend_from_slice(&self.table);
170        // The length written backwards: read from the frame's end.
171        let at = self.out.len();
172        varint(&mut self.out, table_len as u64);
173        self.out[at..].reverse();
174    }
175
176    /// `f` on `v` as a frame, packed in this packer's buffers: a frame built
177    /// without allocating once they've grown to the caller's messages.
178    pub fn with_frame<T: Schema, R>(&mut self, v: &T, f: impl FnOnce(&[u8]) -> R) -> R {
179        self.clear();
180        v.pack(self);
181        self.seal();
182        let out = f(&self.out);
183        self.clear();
184        out
185    }
186
187    /// Starts over, keeping its buffers.
188    fn clear(&mut self) {
189        self.out.clear();
190        self.table.clear();
191        self.strings.clear();
192    }
193}