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    /// Null.
47    pub fn null(&mut self) -> &mut Self {
48        self.out.push(tag::NULL);
49        self
50    }
51
52    /// A bool.
53    pub fn bool(&mut self, b: bool) -> &mut Self {
54        self.out.push(if b { tag::TRUE } else { tag::FALSE });
55        self
56    }
57
58    /// An integer.
59    pub fn int(&mut self, n: i64) -> &mut Self {
60        self.out.push(tag::INT);
61        varint(&mut self.out, zigzag(n));
62        self
63    }
64
65    /// A float: as an `f32` when it is one exactly.
66    pub fn float(&mut self, f: f64) -> &mut Self {
67        self.out.push(tag::FLOAT);
68        self.out.extend_from_slice(&f.to_le_bytes());
69        self
70    }
71
72    /// A 32-bit float: half the bytes of [`Writer::float`].
73    pub fn float32(&mut self, f: f32) -> &mut Self {
74        self.out.push(tag::FLOAT32);
75        self.out.extend_from_slice(&f.to_le_bytes());
76        self
77    }
78
79    /// A list of floats, packed, no tag each: four bytes each when every
80    /// one is an `f32` exactly ([`tag::FLOATS32`]), else eight.
81    pub fn floats(&mut self, items: &[f64]) -> &mut Self {
82        let narrow = crate::frame::floats::fits_f32(items);
83        self.out
84            .push(if narrow { tag::FLOATS32 } else { tag::FLOATS });
85        varint(&mut self.out, items.len() as u64);
86        if narrow {
87            crate::frame::floats::put_narrow(&mut self.out, items);
88        } else {
89            crate::frame::floats::put_wide(&mut self.out, items);
90        }
91        self
92    }
93
94    /// A list of 32-bit floats, packed: four bytes each, no tag.
95    pub fn floats32(&mut self, items: &[f32]) -> &mut Self {
96        self.out.push(tag::FLOATS32);
97        varint(&mut self.out, items.len() as u64);
98        crate::frame::floats::put_f32s(&mut self.out, items);
99        self
100    }
101
102    /// A string: its bytes the first time, its index after.
103    pub fn str(&mut self, s: &str) -> &mut Self {
104        self.out.push(tag::STR);
105        self.string(s);
106        self
107    }
108
109    /// Bytes as they are.
110    pub fn bytes(&mut self, b: &[u8]) -> &mut Self {
111        self.out.push(tag::BYTES);
112        varint(&mut self.out, b.len() as u64);
113        self.out.extend_from_slice(b);
114        self
115    }
116
117    /// A list of `len` values.
118    pub fn list(&mut self, len: usize) -> &mut Self {
119        self.out.push(tag::LIST);
120        varint(&mut self.out, len as u64);
121        self
122    }
123
124    /// A list of ints, packed (no tag each).
125    pub fn ints(&mut self, items: impl ExactSizeIterator<Item = i64>) -> &mut Self {
126        self.out.push(tag::INTS);
127        varint(&mut self.out, items.len() as u64);
128        for n in items {
129            varint(&mut self.out, zigzag(n));
130        }
131        self
132    }
133
134    /// A stream ([`crate::Stream`]): `len` items, already written apart.
135    pub(crate) fn stream_body(&mut self, len: usize, items: &[u8]) -> &mut Self {
136        let mut count = Vec::new();
137        varint(&mut count, len as u64);
138        self.out.push(tag::STREAM);
139        let body = u32::try_from(count.len() + items.len()).unwrap_or(u32::MAX);
140        self.out.extend_from_slice(&body.to_le_bytes());
141        self.out.extend_from_slice(&count);
142        self.out.extend_from_slice(items);
143        self
144    }
145
146    /// A writer of a stream's body alone (no header).
147    pub(crate) fn body() -> Self {
148        Writer {
149            out: Vec::with_capacity(START_BYTES),
150            strings: Interner::new(),
151        }
152    }
153
154    /// A map of `len` entries, each a [`Writer::key`] and a value.
155    pub fn map(&mut self, len: usize) -> &mut Self {
156        self.out.push(tag::MAP);
157        varint(&mut self.out, len as u64);
158        self
159    }
160
161    /// A map's key.
162    pub fn key(&mut self, k: &str) -> &mut Self {
163        self.string(k);
164        self
165    }
166
167    /// A whole value.
168    pub fn value(&mut self, v: &Value) -> &mut Self {
169        match v {
170            Value::Null => self.null(),
171            Value::Bool(b) => self.bool(*b),
172            Value::Int(n) => self.int(*n),
173            Value::Float(f) => self.float(*f),
174            Value::Str(s) => self.str(s),
175            Value::List(items) => {
176                self.list(items.len());
177                for item in items {
178                    self.value(item);
179                }
180                self
181            }
182            Value::Map(map) => {
183                self.map(map.len());
184                for (key, item) in map.iter() {
185                    self.string(key);
186                    self.value(item);
187                }
188                self
189            }
190            Value::Ref(r) => {
191                self.out.push(tag::REF);
192                self.string(r.kind.as_str());
193                self.string(r.id.as_str());
194                self
195            }
196            Value::Bytes(b) => self.bytes(b),
197        }
198    }
199
200    /// The bytes.
201    #[must_use]
202    pub fn finish(self) -> Vec<u8> {
203        self.out
204    }
205
206    /// `s`: a reference if it was written before, else itself.
207    fn string(&mut self, s: &str) {
208        if let Some(i) = self.strings.find(&self.out, s) {
209            varint(&mut self.out, (i as u64) << 1);
210            return;
211        }
212        varint(&mut self.out, ((s.len() as u64) << 1) | NEW_STRING);
213        let at = self.out.len();
214        self.out.extend_from_slice(s.as_bytes());
215        self.strings.add(&self.out, s, at);
216    }
217}