Skip to main content

yog_data/binary/
decoder.rs

1//! Reading the binary form: as a [`Value`], borrowed as a [`ValueRef`], or
2//! step by step by a schema reading itself ([`crate::Schema::decode`]).
3
4use yog_sync::Arc;
5
6use bumpalo::Bump;
7
8use super::{
9    DecodeError, MAGIC, MAX_DEPTH, NEW_STRING, STREAM_LEN_BYTES, VERSION, read_varint, tag,
10    unzigzag,
11};
12use crate::borrowed::{MapRef, ValueRef};
13use crate::value::{Map, Ref, Res, Value};
14
15/// Strings a decoder makes room for at once: a message's keys and values.
16const STRINGS_START: usize = 16;
17
18/// Bytes of a float, and of a 32-bit one.
19const F64_BYTES: usize = 8;
20const F32_BYTES: usize = 4;
21
22/// Bytes a map entry takes at least: its key and its value's tag.
23const MAP_ENTRY_MIN: usize = 2;
24
25/// Reads the binary form. The step-by-step reads ([`Decoder::int`],
26/// [`Decoder::map`] …) answer `None` for anything but what
27/// [`crate::Schema::encode`] writes there — the schema then reads the
28/// slow way, which says what's wrong.
29pub struct Decoder<'b> {
30    b: &'b [u8],
31    i: usize,
32    strings: Vec<&'b str>,
33    /// Map keys made so far, by table index: each key is allocated once.
34    keys: Vec<Option<Arc<str>>>,
35    depth: usize,
36}
37
38impl<'b> Decoder<'b> {
39    /// After the header: the root value next.
40    pub fn open(bytes: &'b [u8]) -> Result<Self, DecodeError> {
41        let mut d = Decoder {
42            b: bytes,
43            i: 0,
44            strings: Vec::with_capacity(STRINGS_START),
45            keys: Vec::new(),
46            depth: 0,
47        };
48        if !bytes.starts_with(MAGIC) {
49            return Err(d.error("not Yog Data (no `YOGD` header)"));
50        }
51        d.i = MAGIC.len();
52        let version = d.byte()?;
53        if version != VERSION {
54            return Err(d.error(format!(
55                "Yog Data version {version}, this reads version {VERSION}"
56            )));
57        }
58        Ok(d)
59    }
60
61    /// A stream's body ([`crate::Stream`]): its count and values, its strings its own.
62    pub(crate) fn body(bytes: &'b [u8]) -> Self {
63        Decoder {
64            b: bytes,
65            i: 0,
66            strings: Vec::with_capacity(STRINGS_START),
67            keys: Vec::new(),
68            depth: 0,
69        }
70    }
71
72    /// A stream's body: its bytes, read past.
73    fn stream_body(&mut self) -> Result<&'b [u8], DecodeError> {
74        let len = u32::from_le_bytes(self.fixed::<STREAM_LEN_BYTES>()?) as usize;
75        self.take(len)
76    }
77
78    /// A stream's values, decoded as a list.
79    fn stream_values(&mut self) -> Result<Vec<Value>, DecodeError> {
80        let mut d = Decoder::body(self.stream_body()?);
81        d.depth = self.depth;
82        let n = d.count(1)?;
83        let mut items = Vec::with_capacity(n);
84        for _ in 0..n {
85            items.push(d.value()?);
86        }
87        d.end()?;
88        Ok(items)
89    }
90
91    /// Whether every byte was read.
92    pub fn at_end(&self) -> bool {
93        self.i == self.b.len()
94    }
95
96    pub(super) fn end(&self) -> Result<(), DecodeError> {
97        if self.at_end() {
98            Ok(())
99        } else {
100            Err(self.error("bytes after the value"))
101        }
102    }
103
104    fn error(&self, message: impl Into<String>) -> DecodeError {
105        DecodeError {
106            message: message.into(),
107            offset: self.i,
108        }
109    }
110
111    fn byte(&mut self) -> Result<u8, DecodeError> {
112        let b = *self
113            .b
114            .get(self.i)
115            .ok_or_else(|| self.error("unexpected end"))?;
116        self.i += 1;
117        Ok(b)
118    }
119
120    fn varint(&mut self) -> Result<u64, DecodeError> {
121        read_varint(self.b, &mut self.i)
122            .ok_or_else(|| self.error("a varint cut short or longer than 64 bits"))
123    }
124
125    /// A length, checked against what's left: each of the `count` things takes at least `min` bytes.
126    fn count(&mut self, min: usize) -> Result<usize, DecodeError> {
127        let n = self.varint()?;
128        let left = self.b.len() - self.i;
129        if n > (left / min.max(1)) as u64 {
130            return Err(self.error(format!("length {n} past the end ({left} bytes left)")));
131        }
132        Ok(n as usize)
133    }
134
135    fn fixed<const N: usize>(&mut self) -> Result<[u8; N], DecodeError> {
136        let bytes = self
137            .b
138            .get(self.i..self.i + N)
139            .ok_or_else(|| self.error("unexpected end"))?;
140        self.i += N;
141        bytes.try_into().map_err(|_| self.error("unexpected end"))
142    }
143
144    /// `len` bytes.
145    fn take(&mut self, len: usize) -> Result<&'b [u8], DecodeError> {
146        let end = self
147            .i
148            .checked_add(len)
149            .filter(|&e| e <= self.b.len())
150            .ok_or_else(|| self.error("bytes past the end"))?;
151        let out = &self.b[self.i..end];
152        self.i = end;
153        Ok(out)
154    }
155
156    /// A packed list of floats `N` bytes wide: each one's bytes, read in place (no alignment asked).
157    fn packed_floats<const N: usize>(
158        &mut self,
159    ) -> Result<std::slice::Iter<'b, [u8; N]>, DecodeError> {
160        let n = self.count(N)?;
161        let bytes = self.take(n * N)?;
162        Ok(bytes.as_chunks::<N>().0.iter())
163    }
164
165    /// A length and that many bytes.
166    fn length_bytes(&mut self) -> Result<&'b [u8], DecodeError> {
167        let len =
168            usize::try_from(self.varint()?).map_err(|_| self.error("a length beyond memory"))?;
169        self.take(len)
170    }
171
172    /// A string: new (read, and added to the table) or the table's.
173    fn string(&mut self) -> Result<&'b str, DecodeError> {
174        let i = self.string_index()?;
175        Ok(self.strings[i])
176    }
177
178    fn string_index(&mut self) -> Result<usize, DecodeError> {
179        let v = self.varint()?;
180        if v & NEW_STRING == 0 {
181            let i = (v >> 1) as usize;
182            return if i < self.strings.len() {
183                Ok(i)
184            } else {
185                Err(self.error(format!("string {i} isn't in the table")))
186            };
187        }
188        let len = usize::try_from(v >> 1).map_err(|_| self.error("a length beyond memory"))?;
189        let at = self.i;
190        let s = std::str::from_utf8(self.take(len)?).map_err(|_| DecodeError {
191            message: "a string isn't UTF-8".into(),
192            offset: at,
193        })?;
194        self.strings.push(s);
195        Ok(self.strings.len() - 1)
196    }
197
198    /// A map key: shared with every other map that has it.
199    fn shared_key(&mut self) -> Result<Arc<str>, DecodeError> {
200        let i = self.string_index()?;
201        if self.keys.len() <= i {
202            self.keys.resize(i + 1, None);
203        }
204        Ok(self.keys[i]
205            .get_or_insert_with(|| self.strings[i].into())
206            .clone())
207    }
208
209    fn deeper(&mut self) -> Result<(), DecodeError> {
210        self.depth += 1;
211        if self.depth > MAX_DEPTH {
212            return Err(self.error(format!("nested deeper than {MAX_DEPTH} levels")));
213        }
214        Ok(())
215    }
216
217    /// The next value, owned.
218    pub fn value(&mut self) -> Result<Value, DecodeError> {
219        Ok(match self.byte()? {
220            tag::NULL => Value::Null,
221            tag::FALSE => Value::Bool(false),
222            tag::TRUE => Value::Bool(true),
223            tag::INT => Value::Int(unzigzag(self.varint()?)),
224            tag::FLOAT => Value::Float(f64::from_le_bytes(self.fixed()?)),
225            tag::FLOAT32 => Value::Float(f64::from(f32::from_le_bytes(self.fixed()?))),
226            tag::FLOATS => Value::List(
227                self.packed_floats::<F64_BYTES>()?
228                    .map(|f| Value::Float(f64::from_le_bytes(*f)))
229                    .collect(),
230            ),
231            tag::FLOATS32 => Value::List(
232                self.packed_floats::<F32_BYTES>()?
233                    .map(|f| Value::Float(f64::from(f32::from_le_bytes(*f))))
234                    .collect(),
235            ),
236            tag::STR => Value::Str(self.string()?.to_owned()),
237            tag::LIST => {
238                let n = self.count(1)?;
239                self.deeper()?;
240                let mut items = Vec::with_capacity(n);
241                for _ in 0..n {
242                    items.push(self.value()?);
243                }
244                self.depth -= 1;
245                Value::List(items)
246            }
247            tag::MAP => {
248                let n = self.count(MAP_ENTRY_MIN)?;
249                self.deeper()?;
250                let mut map = Map::with_capacity(n);
251                for _ in 0..n {
252                    let k = self.shared_key()?;
253                    map.push_unchecked(k, self.value()?);
254                }
255                self.depth -= 1;
256                Value::Map(map)
257            }
258            t @ (tag::REF | tag::TAG) => {
259                let r = Ref {
260                    kind: self.string()?.to_owned(),
261                    id: self.string()?.to_owned(),
262                };
263                if t == tag::REF {
264                    Value::Ref(r)
265                } else {
266                    Value::Tag(r)
267                }
268            }
269            tag::RES => Value::Res(Res {
270                set: self.string()?.to_owned(),
271                key: self.string()?.to_owned(),
272            }),
273            tag::TEXT => Value::Text(self.string()?.to_owned()),
274            tag::IMAGE => Value::Image(self.string()?.to_owned()),
275            tag::COLOR => Value::Color(u32::from_le_bytes(self.fixed()?)),
276            tag::LANG => Value::Lang(self.string()?.to_owned()),
277            tag::BYTES => Value::Bytes(self.length_bytes()?.to_vec()),
278            tag::INTS => {
279                let n = self.count(1)?;
280                let mut items = Vec::with_capacity(n);
281                for _ in 0..n {
282                    items.push(Value::Int(unzigzag(self.varint()?)));
283                }
284                Value::List(items)
285            }
286            tag::STREAM => Value::List(self.stream_values()?),
287            t => {
288                self.i -= 1;
289                return Err(self.error(format!("unknown tag {t}")));
290            }
291        })
292    }
293
294    /// The next value, borrowed: strings point into the bytes, lists and maps go in `arena`.
295    pub fn value_ref<'a>(&mut self, arena: &'a Bump) -> Result<ValueRef<'a>, DecodeError>
296    where
297        'b: 'a,
298    {
299        let mut stack = Vec::new();
300        self.value_ref_in(arena, &mut stack)
301    }
302
303    /// [`Decoder::value_ref`]: children gather on `stack`, then move into `arena` as one slice.
304    fn value_ref_in<'a>(
305        &mut self,
306        arena: &'a Bump,
307        stack: &mut Vec<ValueRef<'a>>,
308    ) -> Result<ValueRef<'a>, DecodeError>
309    where
310        'b: 'a,
311    {
312        Ok(match self.byte()? {
313            tag::NULL => ValueRef::Null,
314            tag::FALSE => ValueRef::Bool(false),
315            tag::TRUE => ValueRef::Bool(true),
316            tag::INT => ValueRef::Int(unzigzag(self.varint()?)),
317            tag::FLOAT => ValueRef::Float(f64::from_le_bytes(self.fixed()?)),
318            tag::FLOAT32 => ValueRef::Float(f64::from(f32::from_le_bytes(self.fixed()?))),
319            t @ (tag::FLOATS | tag::FLOATS32) => self.floats_ref(arena, t == tag::FLOATS)?,
320            tag::STR => ValueRef::Str(self.string()?),
321            tag::LIST => {
322                let n = self.count(1)?;
323                self.deeper()?;
324                let items = self.items_ref(arena, stack, n)?;
325                self.depth -= 1;
326                ValueRef::List(items)
327            }
328            tag::MAP => self.map_ref(arena, stack)?,
329            t @ (tag::REF | tag::TAG) => {
330                let (kind, id) = (self.string()?, self.string()?);
331                if t == tag::REF {
332                    ValueRef::Ref { kind, id }
333                } else {
334                    ValueRef::Tag { kind, id }
335                }
336            }
337            tag::RES => ValueRef::Res {
338                set: self.string()?,
339                key: self.string()?,
340            },
341            tag::TEXT => ValueRef::Text(self.string()?),
342            tag::IMAGE => ValueRef::Image(self.string()?),
343            tag::COLOR => ValueRef::Color(u32::from_le_bytes(self.fixed()?)),
344            tag::LANG => ValueRef::Lang(self.string()?),
345            tag::BYTES => ValueRef::Bytes(self.length_bytes()?),
346            tag::INTS => self.ints_ref(arena)?,
347            tag::STREAM => {
348                let mut d = Decoder::body(self.stream_body()?);
349                d.depth = self.depth;
350                let n = d.count(1)?;
351                let items = d.items_ref(arena, stack, n)?;
352                d.end()?;
353                ValueRef::List(items)
354            }
355            t => {
356                self.i -= 1;
357                return Err(self.error(format!("unknown tag {t}")));
358            }
359        })
360    }
361
362    /// `n` values gathered on `stack`, then moved into `arena` as one slice.
363    fn items_ref<'a>(
364        &mut self,
365        arena: &'a Bump,
366        stack: &mut Vec<ValueRef<'a>>,
367        n: usize,
368    ) -> Result<&'a [ValueRef<'a>], DecodeError>
369    where
370        'b: 'a,
371    {
372        let start = stack.len();
373        for _ in 0..n {
374            let v = self.value_ref_in(arena, stack)?;
375            stack.push(v);
376        }
377        let items = arena.alloc_slice_copy(&stack[start..]);
378        stack.truncate(start);
379        Ok(items)
380    }
381
382    fn map_ref<'a>(
383        &mut self,
384        arena: &'a Bump,
385        stack: &mut Vec<ValueRef<'a>>,
386    ) -> Result<ValueRef<'a>, DecodeError>
387    where
388        'b: 'a,
389    {
390        let n = self.count(MAP_ENTRY_MIN)?;
391        self.deeper()?;
392        let mut entries = bumpalo::collections::Vec::with_capacity_in(n, arena);
393        for _ in 0..n {
394            let k = self.string()?;
395            entries.push((k, self.value_ref_in(arena, stack)?));
396        }
397        self.depth -= 1;
398        Ok(ValueRef::Map(MapRef(entries.into_bump_slice())))
399    }
400
401    fn ints_ref<'a>(&mut self, arena: &'a Bump) -> Result<ValueRef<'a>, DecodeError> {
402        let n = self.count(1)?;
403        let mut items = bumpalo::collections::Vec::with_capacity_in(n, arena);
404        for _ in 0..n {
405            items.push(ValueRef::Int(unzigzag(self.varint()?)));
406        }
407        Ok(ValueRef::List(items.into_bump_slice()))
408    }
409
410    /// A list of floats: eight bytes each (`wide`) or four.
411    fn floats_ref<'a>(&mut self, arena: &'a Bump, wide: bool) -> Result<ValueRef<'a>, DecodeError> {
412        let items: Vec<ValueRef<'a>> = if wide {
413            self.packed_floats::<F64_BYTES>()?
414                .map(|f| ValueRef::Float(f64::from_le_bytes(*f)))
415                .collect()
416        } else {
417            self.packed_floats::<F32_BYTES>()?
418                .map(|f| ValueRef::Float(f64::from(f32::from_le_bytes(*f))))
419                .collect()
420        };
421        Ok(ValueRef::List(arena.alloc_slice_copy(&items)))
422    }
423
424    // ── Step by step, for a schema reading itself ───────────────────────────
425
426    /// The next tag, if it's `t`: read.
427    fn next_is(&mut self, t: u8) -> Option<()> {
428        (self.b.get(self.i) == Some(&t)).then(|| self.i += 1)
429    }
430
431    /// Whether a null is next: read if it is.
432    pub fn null(&mut self) -> bool {
433        self.next_is(tag::NULL).is_some()
434    }
435
436    pub fn bool(&mut self) -> Option<bool> {
437        match *self.b.get(self.i)? {
438            tag::FALSE | tag::TRUE => {
439                self.i += 1;
440                Some(self.b[self.i - 1] == tag::TRUE)
441            }
442            _ => None,
443        }
444    }
445
446    pub fn int(&mut self) -> Option<i64> {
447        self.next_is(tag::INT)?;
448        self.varint().ok().map(unzigzag)
449    }
450
451    /// A float — or an int, as a number.
452    pub fn float(&mut self) -> Option<f64> {
453        match *self.b.get(self.i)? {
454            tag::FLOAT => {
455                self.i += 1;
456                self.fixed().ok().map(f64::from_le_bytes)
457            }
458            tag::FLOAT32 => {
459                self.i += 1;
460                self.fixed().ok().map(|b| f64::from(f32::from_le_bytes(b)))
461            }
462            tag::INT => self.int().map(|n| n as f64),
463            _ => None,
464        }
465    }
466
467    pub fn str(&mut self) -> Option<&'b str> {
468        self.next_is(tag::STR)?;
469        self.string().ok()
470    }
471
472    pub fn bytes(&mut self) -> Option<&'b [u8]> {
473        self.next_is(tag::BYTES)?;
474        self.length_bytes().ok()
475    }
476
477    /// A list next: how many values; [`Decoder::leave`] after them.
478    pub fn list(&mut self) -> Option<usize> {
479        self.next_is(tag::LIST)?;
480        let n = self.count(1).ok()?;
481        self.deeper().ok()?;
482        Some(n)
483    }
484
485    /// A packed list of ints next ([`Decoder::packed_int`] each): how many.
486    pub fn ints(&mut self) -> Option<usize> {
487        self.next_is(tag::INTS)?;
488        self.count(1).ok()
489    }
490
491    /// A stream next: its body (count and values, strings its own).
492    pub fn stream(&mut self) -> Option<&'b [u8]> {
493        self.next_is(tag::STREAM)?;
494        self.stream_body().ok()
495    }
496
497    /// What's left to read.
498    pub(crate) fn rest(&self) -> &'b [u8] {
499        &self.b[self.i..]
500    }
501
502    /// A stream body's count, first thing in it.
503    pub(crate) fn stream_count(&mut self) -> Option<usize> {
504        self.count(1).ok()
505    }
506
507    /// A packed list of floats next: each one.
508    /// (Written narrow when they fit: widened back.)
509    pub fn floats(&mut self) -> Option<Vec<f64>> {
510        if self.next_is(tag::FLOATS32).is_some() {
511            return Some(crate::frame::floats::widen(
512                self.packed_floats::<F32_BYTES>()
513                    .ok()?
514                    .as_slice()
515                    .as_flattened(),
516            ));
517        }
518        self.next_is(tag::FLOATS)?;
519        Some(
520            self.packed_floats::<F64_BYTES>()
521                .ok()?
522                .map(|f| f64::from_le_bytes(*f))
523                .collect(),
524        )
525    }
526
527    /// A packed list of 32-bit floats next: each one.
528    pub fn floats32(&mut self) -> Option<Vec<f32>> {
529        self.next_is(tag::FLOATS32)?;
530        Some(
531            self.packed_floats::<F32_BYTES>()
532                .ok()?
533                .map(|f| f32::from_le_bytes(*f))
534                .collect(),
535        )
536    }
537
538    /// One int of a packed list.
539    pub fn packed_int(&mut self) -> Option<i64> {
540        self.varint().ok().map(unzigzag)
541    }
542
543    /// A map next: how many entries, each a [`Decoder::key`] and a value;
544    /// [`Decoder::leave`] after them.
545    pub fn map(&mut self) -> Option<usize> {
546        self.next_is(tag::MAP)?;
547        let n = self.count(MAP_ENTRY_MIN).ok()?;
548        self.deeper().ok()?;
549        Some(n)
550    }
551
552    /// The end of a list or map.
553    pub fn leave(&mut self) {
554        self.depth = self.depth.saturating_sub(1);
555    }
556
557    pub fn key(&mut self) -> Option<&'b str> {
558        self.string().ok()
559    }
560
561    /// The next value, read and left (its strings still join the table).
562    pub fn skip(&mut self) -> Option<()> {
563        let arena = Bump::new();
564        self.value_ref(&arena).ok().map(drop)
565    }
566}