substrate_data/wire/binary/decode/
decoder.rs1use super::shape::{Shapes, Walk};
7use crate::binary::{
8 DecodeError, LEGACY_VERSION, MAGIC, MAX_DEPTH, NEW_STRING, STR_INDEX_COUNT, STREAM_LEN_BYTES,
9 VERSION, read_varint, tag,
10};
11use crate::model::value::{KindName, Value};
12use crate::sync::Arc;
13
14pub(in crate::wire::binary) const STRINGS_START: usize = 16;
16
17pub(in crate::wire::binary) const F64_BYTES: usize = 8;
19pub(in crate::wire::binary) const F32_BYTES: usize = 4;
20
21pub(in crate::wire::binary) const MAP_ENTRY_MIN: usize = 2;
23
24#[derive(Debug)]
29pub struct Decoder<'b> {
30 pub(in crate::wire::binary) b: &'b [u8],
31 pub(in crate::wire::binary) i: usize,
32 pub(in crate::wire::binary) strings: Vec<&'b str>,
33 pub(in crate::wire::binary) keys: Vec<Option<Arc<str>>>,
35 pub(in crate::wire::binary) kinds: Vec<Option<KindName>>,
37 pub(in crate::wire::binary) depth: usize,
38 pub(in crate::wire::binary) v2: bool,
41 pub(in crate::wire::binary) shapes: Shapes,
43 pub(in crate::wire::binary) frames: Vec<Walk>,
45}
46
47impl<'b> Decoder<'b> {
48 pub fn open(bytes: &'b [u8]) -> Result<Self, DecodeError> {
55 let mut d = Decoder::body(bytes);
56 d.v2 = false;
57 if !bytes.starts_with(MAGIC) {
58 return Err(d.error("not Substrate Data (no `SDAT` header)"));
59 }
60 d.i = MAGIC.len();
61 let version = d.byte()?;
62 match version {
63 VERSION => d.v2 = true,
64 LEGACY_VERSION => {}
65 _ => {
66 return Err(d.error(format!(
67 "Substrate Data version {version}, this reads versions {LEGACY_VERSION} and {VERSION}"
68 )));
69 }
70 }
71 Ok(d)
72 }
73
74 pub(crate) fn body(bytes: &'b [u8]) -> Self {
77 Decoder {
78 b: bytes,
79 i: 0,
80 strings: Vec::with_capacity(STRINGS_START),
81 keys: Vec::new(),
82 kinds: Vec::new(),
83 depth: 0,
84 v2: true,
85 shapes: Shapes::default(),
86 frames: Vec::new(),
87 }
88 }
89
90 pub(in crate::wire::binary) fn inner(&self, bytes: &'b [u8]) -> Self {
92 let mut d = Decoder::body(bytes);
93 d.v2 = self.v2;
94 d.depth = self.depth;
95 d
96 }
97
98 pub(in crate::wire::binary) fn stream_body(&mut self) -> Result<&'b [u8], DecodeError> {
100 let len = u32::from_le_bytes(self.fixed::<STREAM_LEN_BYTES>()?) as usize;
101 self.take(len)
102 }
103
104 pub(in crate::wire::binary) fn stream_values(&mut self) -> Result<Vec<Value>, DecodeError> {
106 let body = self.stream_body()?;
107 let mut d = self.inner(body);
108 let n = d.count(1)?;
109 let mut items = Vec::with_capacity(n);
110 for _ in 0..n {
111 items.push(d.value()?);
112 }
113 d.end()?;
114 Ok(items)
115 }
116
117 #[must_use]
119 pub fn at_end(&self) -> bool {
120 self.i == self.b.len()
121 }
122
123 pub(in crate::wire::binary) fn end(&self) -> Result<(), DecodeError> {
124 if self.at_end() {
125 Ok(())
126 } else {
127 Err(self.error("bytes after the value"))
128 }
129 }
130
131 pub(in crate::wire::binary) fn error(&self, message: impl Into<String>) -> DecodeError {
132 DecodeError {
133 message: message.into(),
134 offset: self.i,
135 }
136 }
137
138 pub(in crate::wire::binary) fn byte(&mut self) -> Result<u8, DecodeError> {
139 let b = *self
140 .b
141 .get(self.i)
142 .ok_or_else(|| self.error("unexpected end"))?;
143 self.i += 1;
144 Ok(b)
145 }
146
147 pub(in crate::wire::binary) fn varint(&mut self) -> Result<u64, DecodeError> {
148 read_varint(self.b, &mut self.i)
149 .ok_or_else(|| self.error("a varint cut short or longer than 64 bits"))
150 }
151
152 pub(in crate::wire::binary) fn count(&mut self, min: usize) -> Result<usize, DecodeError> {
154 let n = self.varint()?;
155 let left = self.b.len() - self.i;
156 match usize::try_from(n) {
157 Ok(n) if n <= left / min.max(1) => Ok(n),
158 _ => Err(self.error(format!("length {n} past the end ({left} bytes left)"))),
159 }
160 }
161
162 pub(in crate::wire::binary) fn fixed<const N: usize>(
163 &mut self,
164 ) -> Result<[u8; N], DecodeError> {
165 let bytes = self
166 .b
167 .get(self.i..self.i + N)
168 .ok_or_else(|| self.error("unexpected end"))?;
169 self.i += N;
170 bytes.try_into().map_err(|_| self.error("unexpected end"))
171 }
172
173 pub(in crate::wire::binary) fn take(&mut self, len: usize) -> Result<&'b [u8], DecodeError> {
175 let end = self
176 .i
177 .checked_add(len)
178 .filter(|&e| e <= self.b.len())
179 .ok_or_else(|| self.error("bytes past the end"))?;
180 let out = &self.b[self.i..end];
181 self.i = end;
182 Ok(out)
183 }
184
185 pub(in crate::wire::binary) fn packed_floats<const N: usize>(
187 &mut self,
188 ) -> Result<std::slice::Iter<'b, [u8; N]>, DecodeError> {
189 let n = self.count(N)?;
190 let bytes = self.take(n * N)?;
191 Ok(bytes.as_chunks::<N>().0.iter())
192 }
193
194 pub(in crate::wire::binary) fn length_bytes(&mut self) -> Result<&'b [u8], DecodeError> {
196 let len =
197 usize::try_from(self.varint()?).map_err(|_| self.error("a length beyond memory"))?;
198 self.take(len)
199 }
200
201 pub(in crate::wire::binary) fn string(&mut self) -> Result<&'b str, DecodeError> {
203 let i = self.string_index()?;
204 Ok(self.strings[i])
205 }
206
207 pub(in crate::wire::binary) fn indexed(&self, t: u8) -> Result<&'b str, DecodeError> {
209 let i = usize::from(t - tag::STR_INDEX);
210 self.strings
211 .get(i)
212 .copied()
213 .ok_or_else(|| self.error(format!("string {i} isn't in the table")))
214 }
215
216 pub(in crate::wire::binary) fn is_indexed(&self, t: u8) -> bool {
218 self.v2 && t.wrapping_sub(tag::STR_INDEX) < STR_INDEX_COUNT
219 }
220
221 pub(in crate::wire::binary) fn is_inline_int(&self, t: u8) -> bool {
223 self.v2 && t >= tag::INT_INLINE
224 }
225
226 pub(in crate::wire::binary) fn string_index(&mut self) -> Result<usize, DecodeError> {
227 let v = self.varint()?;
228 if v & NEW_STRING == 0 {
229 let i = (v >> 1) as usize;
230 return if i < self.strings.len() {
231 Ok(i)
232 } else {
233 Err(self.error(format!("string {i} isn't in the table")))
234 };
235 }
236 let len = usize::try_from(v >> 1).map_err(|_| self.error("a length beyond memory"))?;
237 let at = self.i;
238 let s = crate::utf8::from_utf8(self.take(len)?).map_err(|_| DecodeError {
239 message: "a string isn't UTF-8".into(),
240 offset: at,
241 })?;
242 self.strings.push(s);
243 Ok(self.strings.len() - 1)
244 }
245
246 pub(in crate::wire::binary) fn shared_key_at(&mut self, i: usize) -> Arc<str> {
248 if self.keys.len() <= i {
249 self.keys.resize(i + 1, None);
250 }
251 self.keys[i]
252 .get_or_insert_with(|| self.strings[i].into())
253 .clone()
254 }
255
256 pub(in crate::wire::binary) fn deeper(&mut self) -> Result<(), DecodeError> {
257 self.depth += 1;
258 if self.depth > MAX_DEPTH {
259 return Err(self.error(format!("nested deeper than {MAX_DEPTH} levels")));
260 }
261 Ok(())
262 }
263}