Skip to main content

substrate_data/wire/binary/
writer.rs

1//! Writing the binary form: one buffer, strings written where first used.
2
3use super::interner::Interner;
4use super::{MAGIC, NEW_STRING, VERSION, tag, varint, zigzag};
5use crate::model::value::Value;
6
7/// What a writer reserves to start with: most messages fit.
8pub(crate) const START_BYTES: usize = 256;
9
10/// Writes the binary form piece by piece, from data that isn't a [`Value`]
11/// — nothing is built or copied on the way. A map or list is given its
12/// length, then that many entries (`key` then a value) or values.
13///
14/// ```
15/// let mut w = substrate_data::binary::Writer::new();
16/// w.map(2).key("id").str("docs/intro").key("count").int(3);
17/// let v = substrate_data::binary::decode(&w.finish()).unwrap();
18/// assert_eq!(v.get("count").and_then(|c| c.as_i64()), Some(3));
19/// ```
20#[derive(Debug)]
21pub struct Writer {
22    out: Vec<u8>,
23    /// The strings written, by where they are in `out`.
24    strings: Interner,
25}
26
27impl Default for Writer {
28    fn default() -> Self {
29        Self::new()
30    }
31}
32
33impl Writer {
34    /// A writer of a whole document: the header first.
35    #[must_use]
36    pub fn new() -> Self {
37        let mut out = Vec::with_capacity(START_BYTES);
38        out.extend_from_slice(MAGIC);
39        out.push(VERSION);
40        Writer {
41            out,
42            strings: Interner::new(),
43        }
44    }
45
46    /// A writer that appends a whole document (header first) to `out`,
47    /// which it takes: [`Writer::finish`] gives it back.
48    pub(crate) fn appending(mut out: Vec<u8>) -> Self {
49        out.extend_from_slice(MAGIC);
50        out.push(VERSION);
51        Writer {
52            out,
53            strings: Interner::new(),
54        }
55    }
56
57    /// Starts a new document after `prefix` zeroed bytes, keeping every
58    /// buffer it has grown: a message written without allocating.
59    pub(crate) fn restart(&mut self, prefix: usize) {
60        self.out.clear();
61        self.out.resize(prefix, 0);
62        self.out.extend_from_slice(MAGIC);
63        self.out.push(VERSION);
64        self.strings.clear();
65    }
66
67    /// What is written so far, to patch or send.
68    pub(crate) fn buffer_mut(&mut self) -> &mut Vec<u8> {
69        &mut self.out
70    }
71
72    /// Null.
73    pub fn null(&mut self) -> &mut Self {
74        self.out.push(tag::NULL);
75        self
76    }
77
78    /// A bool.
79    pub fn bool(&mut self, b: bool) -> &mut Self {
80        self.out.push(if b { tag::TRUE } else { tag::FALSE });
81        self
82    }
83
84    /// An integer.
85    pub fn int(&mut self, n: i64) -> &mut Self {
86        self.out.push(tag::INT);
87        varint(&mut self.out, zigzag(n));
88        self
89    }
90
91    /// A float, eight bytes ([`Writer::float32`] writes four).
92    pub fn float(&mut self, f: f64) -> &mut Self {
93        self.out.push(tag::FLOAT);
94        self.out.extend_from_slice(&f.to_le_bytes());
95        self
96    }
97
98    /// A 32-bit float: half the bytes of [`Writer::float`].
99    pub fn float32(&mut self, f: f32) -> &mut Self {
100        self.out.push(tag::FLOAT32);
101        self.out.extend_from_slice(&f.to_le_bytes());
102        self
103    }
104
105    /// A list of floats, packed, no tag each: four bytes each when every
106    /// one is an `f32` exactly ([`tag::FLOATS32`]), else eight.
107    pub fn floats(&mut self, items: &[f64]) -> &mut Self {
108        let narrow = crate::frame::floats::fits_f32(items);
109        self.out
110            .push(if narrow { tag::FLOATS32 } else { tag::FLOATS });
111        varint(&mut self.out, items.len() as u64);
112        if narrow {
113            crate::frame::floats::put_narrow(&mut self.out, items);
114        } else {
115            crate::frame::floats::put_wide(&mut self.out, items);
116        }
117        self
118    }
119
120    /// A list of 32-bit floats, packed: four bytes each, no tag.
121    pub fn floats32(&mut self, items: &[f32]) -> &mut Self {
122        self.out.push(tag::FLOATS32);
123        varint(&mut self.out, items.len() as u64);
124        crate::frame::floats::put_f32s(&mut self.out, items);
125        self
126    }
127
128    /// A string: its bytes the first time, its index after.
129    pub fn str(&mut self, s: &str) -> &mut Self {
130        self.out.push(tag::STR);
131        self.string(s);
132        self
133    }
134
135    /// Bytes as they are.
136    pub fn bytes(&mut self, b: &[u8]) -> &mut Self {
137        self.out.push(tag::BYTES);
138        varint(&mut self.out, b.len() as u64);
139        self.out.extend_from_slice(b);
140        self
141    }
142
143    /// A list of `len` values.
144    pub fn list(&mut self, len: usize) -> &mut Self {
145        self.out.push(tag::LIST);
146        varint(&mut self.out, len as u64);
147        self
148    }
149
150    /// A list of ints, packed (no tag each).
151    pub fn ints(&mut self, items: impl ExactSizeIterator<Item = i64>) -> &mut Self {
152        self.out.push(tag::INTS);
153        varint(&mut self.out, items.len() as u64);
154        for n in items {
155            varint(&mut self.out, zigzag(n));
156        }
157        self
158    }
159
160    /// A stream ([`crate::Stream`]): `len` items, already written apart.
161    pub(crate) fn stream_body(&mut self, len: usize, items: &[u8]) -> &mut Self {
162        let mut count = Vec::new();
163        varint(&mut count, len as u64);
164        self.out.push(tag::STREAM);
165        let body = u32::try_from(count.len() + items.len()).unwrap_or(u32::MAX);
166        self.out.extend_from_slice(&body.to_le_bytes());
167        self.out.extend_from_slice(&count);
168        self.out.extend_from_slice(items);
169        self
170    }
171
172    /// A writer of a stream's body alone (no header).
173    pub(crate) fn body() -> Self {
174        Writer {
175            out: Vec::with_capacity(START_BYTES),
176            strings: Interner::new(),
177        }
178    }
179
180    /// A map of `len` entries, each a [`Writer::key`] and a value.
181    pub fn map(&mut self, len: usize) -> &mut Self {
182        self.out.push(tag::MAP);
183        varint(&mut self.out, len as u64);
184        self
185    }
186
187    /// A map's key.
188    pub fn key(&mut self, k: &str) -> &mut Self {
189        self.string(k);
190        self
191    }
192
193    /// A whole value.
194    pub fn value(&mut self, v: &Value) -> &mut Self {
195        match v {
196            Value::Null => self.null(),
197            Value::Bool(b) => self.bool(*b),
198            Value::Int(n) => self.int(*n),
199            Value::Float(f) => self.float(*f),
200            Value::Str(s) => self.str(s),
201            Value::List(items) => {
202                self.list(items.len());
203                for item in items {
204                    self.value(item);
205                }
206                self
207            }
208            Value::Map(map) => {
209                self.map(map.len());
210                for (key, item) in map.iter() {
211                    self.string(key);
212                    self.value(item);
213                }
214                self
215            }
216            Value::Ref(r) => {
217                self.out.push(tag::REF);
218                self.string(r.kind.as_str());
219                self.string(r.id.as_str());
220                self
221            }
222            Value::Bytes(b) => self.bytes(b),
223        }
224    }
225
226    /// The bytes.
227    #[must_use]
228    pub fn finish(self) -> Vec<u8> {
229        self.out
230    }
231
232    /// `s`: a reference if it was written before, else itself.
233    fn string(&mut self, s: &str) {
234        if let Some(i) = self.strings.find(&self.out, s) {
235            varint(&mut self.out, (i as u64) << 1);
236            return;
237        }
238        varint(&mut self.out, ((s.len() as u64) << 1) | NEW_STRING);
239        let at = self.out.len();
240        self.out.extend_from_slice(s.as_bytes());
241        self.strings.add(&self.out, s, at);
242    }
243}