Skip to main content

substrate_data/wire/binary/decode/
decoder_straight.rs

1//! [`Decoder`] step by step, for a schema reading itself
2//! ([`crate::Schema::decode`]): `None` for anything but what
3//! [`crate::Schema::encode`] writes there.
4
5use bumpalo::Bump;
6
7use super::decoder::{F32_BYTES, F64_BYTES, MAP_ENTRY_MIN};
8use super::decoder_value::inline_int;
9use super::shape::Walk;
10use crate::binary::{Decoder, tag, unzigzag};
11use crate::model::number::int_to_f64;
12
13impl<'b> Decoder<'b> {
14    /// The next tag, if it's `t`: read.
15    fn next_is(&mut self, t: u8) -> Option<()> {
16        (self.b.get(self.i) == Some(&t)).then(|| self.i += 1)
17    }
18
19    /// Whether a null is next: read if it is.
20    pub fn null(&mut self) -> bool {
21        self.next_is(tag::NULL).is_some()
22    }
23
24    /// A bool, if one is next.
25    pub fn bool(&mut self) -> Option<bool> {
26        match *self.b.get(self.i)? {
27            tag::FALSE | tag::TRUE => {
28                self.i += 1;
29                Some(self.b[self.i - 1] == tag::TRUE)
30            }
31            _ => None,
32        }
33    }
34
35    /// An integer, if one is next.
36    pub fn int(&mut self) -> Option<i64> {
37        let t = *self.b.get(self.i)?;
38        if self.is_inline_int(t) {
39            self.i += 1;
40            return Some(inline_int(t));
41        }
42        self.next_is(tag::INT)?;
43        self.varint().ok().map(unzigzag)
44    }
45
46    /// A float — or an int, as a number.
47    pub fn float(&mut self) -> Option<f64> {
48        match *self.b.get(self.i)? {
49            tag::FLOAT => {
50                self.i += 1;
51                self.fixed().ok().map(f64::from_le_bytes)
52            }
53            tag::FLOAT32 => {
54                self.i += 1;
55                self.fixed().ok().map(|b| f64::from(f32::from_le_bytes(b)))
56            }
57            t if t == tag::INT || self.is_inline_int(t) => self.int().map(int_to_f64),
58            _ => None,
59        }
60    }
61
62    /// A string, if one is next.
63    pub fn str(&mut self) -> Option<&'b str> {
64        let t = *self.b.get(self.i)?;
65        if self.is_indexed(t) {
66            self.i += 1;
67            return self.indexed(t).ok();
68        }
69        self.next_is(tag::STR)?;
70        self.string().ok()
71    }
72
73    /// Bytes, if they're next.
74    pub fn bytes(&mut self) -> Option<&'b [u8]> {
75        self.next_is(tag::BYTES)?;
76        self.length_bytes().ok()
77    }
78
79    /// A list next: how many values; [`Decoder::leave`] after them.
80    pub fn list(&mut self) -> Option<usize> {
81        self.next_is(tag::LIST)?;
82        let n = self.count(1).ok()?;
83        self.deeper().ok()?;
84        Some(n)
85    }
86
87    /// A packed list of ints next ([`Decoder::packed_int`] each): how many.
88    pub fn ints(&mut self) -> Option<usize> {
89        self.next_is(tag::INTS)?;
90        self.count(1).ok()
91    }
92
93    /// A stream next: its body (count and values, strings its own).
94    pub fn stream(&mut self) -> Option<&'b [u8]> {
95        self.next_is(tag::STREAM)?;
96        self.stream_body().ok()
97    }
98
99    /// What's left to read.
100    pub(crate) fn rest(&self) -> &'b [u8] {
101        &self.b[self.i..]
102    }
103
104    /// A stream body's count, first thing in it.
105    pub(crate) fn stream_count(&mut self) -> Option<usize> {
106        self.count(1).ok()
107    }
108
109    /// A packed list of floats next: each one.
110    /// (Written narrow when they fit: widened back.)
111    pub fn floats(&mut self) -> Option<Vec<f64>> {
112        if self.next_is(tag::FLOATS32).is_some() {
113            return Some(crate::frame::floats::widen(
114                self.packed_floats::<F32_BYTES>()
115                    .ok()?
116                    .as_slice()
117                    .as_flattened(),
118            ));
119        }
120        self.next_is(tag::FLOATS)?;
121        Some(
122            self.packed_floats::<F64_BYTES>()
123                .ok()?
124                .map(|f| f64::from_le_bytes(*f))
125                .collect(),
126        )
127    }
128
129    /// A packed list of 32-bit floats next: each one.
130    pub fn floats32(&mut self) -> Option<Vec<f32>> {
131        self.next_is(tag::FLOATS32)?;
132        Some(
133            self.packed_floats::<F32_BYTES>()
134                .ok()?
135                .map(|f| f32::from_le_bytes(*f))
136                .collect(),
137        )
138    }
139
140    /// One int of a packed list.
141    pub fn packed_int(&mut self) -> Option<i64> {
142        self.varint().ok().map(unzigzag)
143    }
144
145    /// A map next: how many entries, each a [`Decoder::key`] and a value;
146    /// [`Decoder::leave`] after them.
147    pub fn map(&mut self) -> Option<usize> {
148        match *self.b.get(self.i)? {
149            tag::MAP => {
150                self.i += 1;
151                let n = self.count(MAP_ENTRY_MIN).ok()?;
152                self.deeper().ok()?;
153                Some(n)
154            }
155            tag::MAP_SHAPE if self.v2 => {
156                self.i += 1;
157                let shape = self.shape_spec().ok()?;
158                let n = self.shape_width(shape).ok()?;
159                self.deeper().ok()?;
160                self.frames.push(Walk {
161                    depth: self.depth,
162                    shape,
163                    next: 0,
164                });
165                Some(n)
166            }
167            _ => None,
168        }
169    }
170
171    /// The end of a list or map.
172    pub fn leave(&mut self) {
173        self.depth = self.depth.saturating_sub(1);
174        if self.frames.last().is_some_and(|f| f.depth > self.depth) {
175            self.frames.pop();
176        }
177    }
178
179    /// A map's next key.
180    pub fn key(&mut self) -> Option<&'b str> {
181        if let Some(frame) = self.frames.last_mut()
182            && frame.depth == self.depth
183        {
184            let string = self.shapes.keys_of(frame.shape).get(frame.next).copied()?;
185            frame.next += 1;
186            return Some(self.strings[string]);
187        }
188        self.string().ok()
189    }
190
191    /// The next value, read and left (its strings still join the table).
192    pub fn skip(&mut self) -> Option<()> {
193        let arena = Bump::new();
194        self.value_ref(&arena).ok().map(drop)
195    }
196}