Skip to main content

yog_data/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::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 = yog_data::binary::Writer::new();
16/// w.map(2).key("id").str("mymod:ruby").key("count").int(3);
17/// let v = yog_data::binary::decode(&w.finish()).unwrap();
18/// assert_eq!(v.get("count").and_then(|c| c.as_i64()), Some(3));
19/// ```
20pub struct Writer {
21    out: Vec<u8>,
22    /// The strings written, by where they are in `out`.
23    strings: Interner,
24}
25
26impl Default for Writer {
27    fn default() -> Self {
28        Self::new()
29    }
30}
31
32impl Writer {
33    pub fn new() -> Self {
34        let mut out = Vec::with_capacity(START_BYTES);
35        out.extend_from_slice(MAGIC);
36        out.push(VERSION);
37        Writer {
38            out,
39            strings: Interner::new(),
40        }
41    }
42
43    pub fn null(&mut self) -> &mut Self {
44        self.out.push(tag::NULL);
45        self
46    }
47
48    pub fn bool(&mut self, b: bool) -> &mut Self {
49        self.out.push(if b { tag::TRUE } else { tag::FALSE });
50        self
51    }
52
53    pub fn int(&mut self, n: i64) -> &mut Self {
54        self.out.push(tag::INT);
55        varint(&mut self.out, zigzag(n));
56        self
57    }
58
59    pub fn float(&mut self, f: f64) -> &mut Self {
60        self.out.push(tag::FLOAT);
61        self.out.extend_from_slice(&f.to_le_bytes());
62        self
63    }
64
65    /// A 32-bit float: half the bytes of [`Writer::float`].
66    pub fn float32(&mut self, f: f32) -> &mut Self {
67        self.out.push(tag::FLOAT32);
68        self.out.extend_from_slice(&f.to_le_bytes());
69        self
70    }
71
72    /// A list of floats, packed, no tag each: four bytes each when every
73    /// one is an `f32` exactly ([`tag::FLOATS32`]), else eight.
74    pub fn floats(&mut self, items: &[f64]) -> &mut Self {
75        let narrow = crate::frame::floats::fits_f32(items);
76        self.out
77            .push(if narrow { tag::FLOATS32 } else { tag::FLOATS });
78        varint(&mut self.out, items.len() as u64);
79        if narrow {
80            crate::frame::floats::put_narrow(&mut self.out, items);
81        } else {
82            crate::frame::floats::put_wide(&mut self.out, items);
83        }
84        self
85    }
86
87    /// A list of 32-bit floats, packed: four bytes each, no tag.
88    pub fn floats32(&mut self, items: &[f32]) -> &mut Self {
89        self.out.push(tag::FLOATS32);
90        varint(&mut self.out, items.len() as u64);
91        crate::frame::floats::put_f32s(&mut self.out, items);
92        self
93    }
94
95    pub fn str(&mut self, s: &str) -> &mut Self {
96        self.out.push(tag::STR);
97        self.string(s);
98        self
99    }
100
101    /// Bytes as they are.
102    pub fn bytes(&mut self, b: &[u8]) -> &mut Self {
103        self.out.push(tag::BYTES);
104        varint(&mut self.out, b.len() as u64);
105        self.out.extend_from_slice(b);
106        self
107    }
108
109    /// A list of `len` values.
110    pub fn list(&mut self, len: usize) -> &mut Self {
111        self.out.push(tag::LIST);
112        varint(&mut self.out, len as u64);
113        self
114    }
115
116    /// A list of ints, packed (no tag each).
117    pub fn ints(&mut self, items: impl ExactSizeIterator<Item = i64>) -> &mut Self {
118        self.out.push(tag::INTS);
119        varint(&mut self.out, items.len() as u64);
120        for n in items {
121            varint(&mut self.out, zigzag(n));
122        }
123        self
124    }
125
126    /// A stream ([`crate::Stream`]): `len` items, already written apart.
127    pub(crate) fn stream_body(&mut self, len: usize, items: &[u8]) -> &mut Self {
128        let mut count = Vec::new();
129        varint(&mut count, len as u64);
130        self.out.push(tag::STREAM);
131        let body = u32::try_from(count.len() + items.len()).unwrap_or(u32::MAX);
132        self.out.extend_from_slice(&body.to_le_bytes());
133        self.out.extend_from_slice(&count);
134        self.out.extend_from_slice(items);
135        self
136    }
137
138    /// A writer of a stream's body alone (no header).
139    pub(crate) fn body() -> Self {
140        Writer {
141            out: Vec::with_capacity(START_BYTES),
142            strings: Interner::new(),
143        }
144    }
145
146    /// A map of `len` entries, each a [`Writer::key`] and a value.
147    pub fn map(&mut self, len: usize) -> &mut Self {
148        self.out.push(tag::MAP);
149        varint(&mut self.out, len as u64);
150        self
151    }
152
153    pub fn key(&mut self, k: &str) -> &mut Self {
154        self.string(k);
155        self
156    }
157
158    pub fn value(&mut self, v: &Value) -> &mut Self {
159        match v {
160            Value::Null => self.null(),
161            Value::Bool(b) => self.bool(*b),
162            Value::Int(n) => self.int(*n),
163            Value::Float(f) => self.float(*f),
164            Value::Str(s) => self.str(s),
165            Value::List(items) => {
166                self.list(items.len());
167                for item in items {
168                    self.value(item);
169                }
170                self
171            }
172            Value::Map(map) => {
173                self.map(map.len());
174                for (k, v) in map.iter() {
175                    self.string(k);
176                    self.value(v);
177                }
178                self
179            }
180            Value::Ref(r) | Value::Tag(r) => {
181                self.out.push(if matches!(v, Value::Ref(_)) {
182                    tag::REF
183                } else {
184                    tag::TAG
185                });
186                self.string(&r.kind);
187                self.string(&r.id);
188                self
189            }
190            Value::Res(r) => {
191                self.out.push(tag::RES);
192                self.string(&r.set);
193                self.string(&r.key);
194                self
195            }
196            Value::Text(s) => self.tagged(tag::TEXT, s),
197            Value::Image(s) => self.tagged(tag::IMAGE, s),
198            Value::Lang(s) => self.tagged(tag::LANG, s),
199            Value::Color(c) => {
200                self.out.push(tag::COLOR);
201                self.out.extend_from_slice(&c.to_le_bytes());
202                self
203            }
204            Value::Bytes(b) => self.bytes(b),
205        }
206    }
207
208    fn tagged(&mut self, t: u8, s: &str) -> &mut Self {
209        self.out.push(t);
210        self.string(s);
211        self
212    }
213
214    /// The bytes.
215    pub fn finish(self) -> Vec<u8> {
216        self.out
217    }
218
219    /// `s`: a reference if it was written before, else itself.
220    fn string(&mut self, s: &str) {
221        if let Some(i) = self.strings.find(&self.out, s) {
222            varint(&mut self.out, (i as u64) << 1);
223            return;
224        }
225        varint(&mut self.out, ((s.len() as u64) << 1) | NEW_STRING);
226        let at = self.out.len();
227        self.out.extend_from_slice(s.as_bytes());
228        self.strings.add(&self.out, s, at);
229    }
230}