1use crate::{core::decoding::reader::span::Span, DecodingError};
2
3#[derive(Clone)]
7pub struct WasmDecoder<'a> {
8 pub full_wasm_binary: &'a [u8],
10
11 pub pc: usize,
27}
28
29impl<'a> WasmDecoder<'a> {
30 pub const fn new(wasm: &'a [u8]) -> Self {
32 Self {
33 full_wasm_binary: wasm,
34 pc: 0,
35 }
36 }
37
38 pub fn move_start_to(&mut self, span: Span) -> Result<(), DecodingError> {
46 if span.from + span.len > self.full_wasm_binary.len() {
47 return Err(DecodingError::Eof);
48 }
49
50 self.pc = span.from;
51
52 Ok(())
53 }
54
55 pub fn remaining_bytes(&self) -> &[u8] {
57 &self.full_wasm_binary[self.pc..]
58 }
59
60 pub fn make_span(&self, len: usize) -> Result<Span, DecodingError> {
65 if self.pc + len > self.full_wasm_binary.len() {
66 return Err(DecodingError::Eof);
67 }
68 Ok(Span::new(self.pc, len))
69 }
70
71 pub fn strip_bytes<const N: usize>(&mut self) -> Result<[u8; N], DecodingError> {
82 if N > self.full_wasm_binary.len() - self.pc {
83 return Err(DecodingError::Eof);
84 }
85
86 let bytes = &self.full_wasm_binary[self.pc..(self.pc + N)];
87 self.pc += N;
88
89 Ok(bytes.try_into().expect("the slice length to be exactly N"))
90 }
91
92 pub fn peek_u8(&self) -> Result<u8, DecodingError> {
96 self.full_wasm_binary
97 .get(self.pc)
98 .copied()
99 .ok_or(DecodingError::Eof)
100 }
101
102 pub fn measure_num_read_bytes<T, E>(
112 &mut self,
113 f: impl FnOnce(&mut WasmDecoder) -> Result<T, E>,
114 ) -> Result<(T, usize), E> {
115 let before = self.pc;
116 let ret = f(self)?;
117
118 debug_assert!(
120 self.pc >= before,
121 "pc was advanced backwards towards the start"
122 );
123
124 let num_read_bytes = self.pc - before;
125 Ok((ret, num_read_bytes))
126 }
127
128 pub fn skip(&mut self, num_bytes: usize) -> Result<(), DecodingError> {
137 if num_bytes > self.full_wasm_binary.len() - self.pc {
138 return Err(DecodingError::Eof);
139 }
140 self.pc += num_bytes;
141 Ok(())
142 }
143
144 pub fn into_inner(self) -> &'a [u8] {
146 self.full_wasm_binary
147 }
148
149 pub fn handle_transaction<T, E>(
154 &mut self,
155 f: impl FnOnce(&mut WasmDecoder<'a>) -> Result<T, E>,
156 ) -> Result<T, E> {
157 let original = self.clone();
158 f(self).inspect_err(|_| {
159 *self = original;
160 })
161 }
162}
163
164pub mod span {
165 use core::ops::Index;
166
167 use crate::core::decoding::reader::WasmDecoder;
168
169 #[derive(Copy, Clone, Debug, Hash)]
175 pub struct Span {
176 pub from: usize,
177 pub len: usize,
178 }
179
180 impl Span {
181 pub const fn new(from: usize, len: usize) -> Self {
183 Self { from, len }
184 }
185
186 pub const fn len(&self) -> usize {
188 self.len
189 }
190
191 pub const fn from(&self) -> usize {
192 self.from
193 }
194 }
195
196 impl<'a> Index<Span> for WasmDecoder<'a> {
197 type Output = [u8];
198
199 fn index(&self, index: Span) -> &'a Self::Output {
200 &self.full_wasm_binary[index.from..(index.from + index.len)]
201 }
202 }
203}
204
205#[cfg(test)]
206mod test {
207 use crate::ValType;
208
209 use super::*;
210 use alloc::vec;
211
212 #[test]
213 fn move_start_to() {
214 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
215 let mut wasm_reader = WasmDecoder::new(&my_bytes);
216
217 let span = Span::new(0, 0);
218 wasm_reader.move_start_to(span).unwrap();
219 wasm_reader.peek_u8().unwrap();
221
222 let span = Span::new(0, my_bytes.len());
223 wasm_reader.move_start_to(span).unwrap();
224 wasm_reader.peek_u8().unwrap();
225 assert_eq!(wasm_reader[span], my_bytes);
226
227 let span = Span::new(my_bytes.len(), 0);
228 wasm_reader.move_start_to(span).unwrap();
229 let span = Span::new(my_bytes.len() - 1, 1);
232 wasm_reader.move_start_to(span).unwrap();
233
234 assert_eq!(wasm_reader.peek_u8().unwrap(), *my_bytes.last().unwrap());
235 }
236
237 #[test]
238 fn move_start_to_out_of_bounds_1() {
239 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
240 let mut wasm_reader = WasmDecoder::new(&my_bytes);
241
242 let span = Span::new(my_bytes.len(), 1);
243 assert_eq!(wasm_reader.move_start_to(span), Err(DecodingError::Eof));
244 }
245
246 #[test]
247 fn move_start_to_out_of_bounds_2() {
248 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
249 let mut wasm_reader = WasmDecoder::new(&my_bytes);
250
251 let span = Span::new(0, my_bytes.len() + 1);
252 assert_eq!(wasm_reader.move_start_to(span), Err(DecodingError::Eof));
253 }
254
255 #[test]
256 fn remaining_bytes_1() {
257 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
258 let mut wasm_reader = WasmDecoder::new(&my_bytes);
259
260 assert_eq!(wasm_reader.remaining_bytes(), my_bytes);
261 wasm_reader.skip(4).unwrap();
262 assert_eq!(wasm_reader.peek_u8().unwrap(), 0x15);
263
264 assert_eq!(wasm_reader.remaining_bytes(), &my_bytes[4..]);
265 }
266
267 #[test]
268 fn remaining_bytes_2() {
269 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
270 let mut wasm_reader = WasmDecoder::new(&my_bytes);
271
272 assert_eq!(wasm_reader.remaining_bytes(), my_bytes);
273 wasm_reader.skip(5).unwrap();
274 assert_eq!(wasm_reader.remaining_bytes(), &my_bytes[5..]);
275 assert_eq!(wasm_reader.remaining_bytes(), &[]);
276 }
277
278 #[test]
279 fn strip_bytes_1() {
280 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
281 let mut wasm_reader = WasmDecoder::new(&my_bytes);
282
283 assert_eq!(wasm_reader.remaining_bytes(), my_bytes);
284 let stripped_bytes = wasm_reader.strip_bytes::<4>().unwrap();
285 assert_eq!(&stripped_bytes, &my_bytes[..4]);
286 assert_eq!(wasm_reader.remaining_bytes(), &[0x15]);
287 }
288
289 #[test]
290 fn strip_bytes_2() {
291 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
292 let mut wasm_reader = WasmDecoder::new(&my_bytes);
293
294 assert_eq!(wasm_reader.remaining_bytes(), my_bytes);
295 wasm_reader.skip(1).unwrap();
296 let stripped_bytes = wasm_reader.strip_bytes::<4>().unwrap();
297 assert_eq!(&stripped_bytes, &my_bytes[1..5]);
298 assert_eq!(wasm_reader.remaining_bytes(), &[]);
299 }
300
301 #[test]
302 fn strip_bytes_3() {
303 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
304 let mut wasm_reader = WasmDecoder::new(&my_bytes);
305
306 assert_eq!(wasm_reader.remaining_bytes(), my_bytes);
307 wasm_reader.skip(2).unwrap();
308 let stripped_bytes = wasm_reader.strip_bytes::<4>();
309 assert_eq!(stripped_bytes, Err(DecodingError::Eof));
310 }
311
312 #[test]
313 fn strip_bytes_4() {
314 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
315 let mut wasm_reader = WasmDecoder::new(&my_bytes);
316
317 assert_eq!(wasm_reader.remaining_bytes(), my_bytes);
318 wasm_reader.skip(5).unwrap();
319 let stripped_bytes = wasm_reader.strip_bytes::<0>().unwrap();
320 assert_eq!(stripped_bytes, [0u8; 0]);
321 }
322
323 #[test]
324 fn skip_1() {
325 let my_bytes = vec![0x11, 0x12, 0x13, 0x14, 0x15];
326 let mut wasm_reader = WasmDecoder::new(&my_bytes);
327 assert_eq!(wasm_reader.remaining_bytes(), my_bytes);
328 assert_eq!(wasm_reader.skip(6), Err(DecodingError::Eof));
329 }
330
331 #[test]
332 fn reader_transaction() {
333 let bytes = [0x1, 0x2, 0x3, 0x4, 0x5, 0x6];
334 let mut reader = WasmDecoder::new(&bytes);
335
336 assert_eq!(
337 reader.handle_transaction(|reader| { reader.strip_bytes::<2>() }),
338 Ok([0x1, 0x2]),
339 );
340
341 let transaction_result: Result<(), DecodingError> = reader.handle_transaction(|reader| {
342 assert_eq!(reader.strip_bytes::<2>(), Ok([0x3, 0x4]));
343
344 Err(DecodingError::InvalidMagic)
346 });
347 assert_eq!(transaction_result, Err(DecodingError::InvalidMagic));
348
349 assert_eq!(reader.strip_bytes::<3>(), Ok([0x3, 0x4, 0x5]));
350 }
351
352 #[test]
353 fn reader_transaction_ergonomics() {
354 let bytes = [0x1, 0x2, 0x3, 0x4, 0x5, 0x6];
355 let mut reader = WasmDecoder::new(&bytes);
356
357 assert_eq!(reader.handle_transaction(WasmDecoder::decode_u8), Ok(0x1));
358
359 assert_eq!(
360 reader.handle_transaction(ValType::decode),
361 Err(DecodingError::MalformedValType)
362 );
363 }
364}