tinywasm_wasmparser/
binary_reader.rs

1/* Copyright 2018 Mozilla Foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16use alloc::boxed::Box;
17use alloc::format;
18use alloc::string::String;
19use alloc::string::ToString;
20use alloc::vec::Vec;
21
22use crate::std::fmt;
23use crate::std::marker;
24use crate::std::ops::Range;
25use crate::std::str;
26use crate::{limits::*, *};
27
28pub(crate) const WASM_MAGIC_NUMBER: &[u8; 4] = b"\0asm";
29
30/// A binary reader for WebAssembly modules.
31#[derive(Debug, Clone)]
32pub struct BinaryReaderError {
33    // Wrap the actual error data in a `Box` so that the error is just one
34    // word. This means that we can continue returning small `Result`s in
35    // registers.
36    pub(crate) inner: Box<BinaryReaderErrorInner>,
37}
38
39#[derive(Debug, Clone)]
40pub(crate) struct BinaryReaderErrorInner {
41    pub(crate) message: String,
42    pub(crate) offset: usize,
43    pub(crate) needed_hint: Option<usize>,
44}
45
46/// The result for `BinaryReader` operations.
47pub type Result<T, E = BinaryReaderError> = crate::std::result::Result<T, E>;
48
49// impl std::error::Error for BinaryReaderError {}
50
51impl fmt::Display for BinaryReaderError {
52    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53        write!(
54            f,
55            "{} (at offset 0x{:x})",
56            self.inner.message, self.inner.offset
57        )
58    }
59}
60
61impl BinaryReaderError {
62    #[cold]
63    pub(crate) fn new(message: impl Into<String>, offset: usize) -> Self {
64        let message = message.into();
65        BinaryReaderError {
66            inner: Box::new(BinaryReaderErrorInner {
67                message,
68                offset,
69                needed_hint: None,
70            }),
71        }
72    }
73
74    #[cold]
75    pub(crate) fn fmt(args: fmt::Arguments<'_>, offset: usize) -> Self {
76        BinaryReaderError::new(args.to_string(), offset)
77    }
78
79    #[cold]
80    pub(crate) fn eof(offset: usize, needed_hint: usize) -> Self {
81        BinaryReaderError {
82            inner: Box::new(BinaryReaderErrorInner {
83                message: "unexpected end-of-file".to_string(),
84                offset,
85                needed_hint: Some(needed_hint),
86            }),
87        }
88    }
89
90    /// Get this error's message.
91    pub fn message(&self) -> &str {
92        &self.inner.message
93    }
94
95    /// Get the offset within the Wasm binary where the error occurred.
96    pub fn offset(&self) -> usize {
97        self.inner.offset
98    }
99
100    pub(crate) fn add_context(&mut self, mut context: String) {
101        context.push_str("\n");
102        self.inner.message.insert_str(0, &context);
103    }
104}
105
106/// A binary reader of the WebAssembly structures and types.
107#[derive(Clone, Debug, Hash)]
108pub struct BinaryReader<'a> {
109    pub(crate) buffer: &'a [u8],
110    pub(crate) position: usize,
111    original_offset: usize,
112    allow_memarg64: bool,
113}
114
115impl<'a> BinaryReader<'a> {
116    /// Constructs `BinaryReader` type.
117    ///
118    /// # Examples
119    /// ```
120    /// let fn_body = &vec![0x41, 0x00, 0x10, 0x00, 0x0B];
121    /// let mut reader = tinywasm_wasmparser::BinaryReader::new(fn_body);
122    /// while !reader.eof() {
123    ///     let op = reader.read_operator();
124    ///     println!("{:?}", op)
125    /// }
126    /// ```
127    pub fn new(data: &[u8]) -> BinaryReader {
128        BinaryReader {
129            buffer: data,
130            position: 0,
131            original_offset: 0,
132            allow_memarg64: false,
133        }
134    }
135
136    /// Constructs a `BinaryReader` with an explicit starting offset.
137    pub fn new_with_offset(data: &[u8], original_offset: usize) -> BinaryReader {
138        BinaryReader {
139            buffer: data,
140            position: 0,
141            original_offset,
142            allow_memarg64: false,
143        }
144    }
145
146    /// Gets the original position of the binary reader.
147    #[inline]
148    pub fn original_position(&self) -> usize {
149        self.original_offset + self.position
150    }
151
152    /// Whether or not to allow 64-bit memory arguments in functions.
153    ///
154    /// This is intended to be `true` when support for the memory64
155    /// WebAssembly proposal is also enabled.
156    pub fn allow_memarg64(&mut self, allow: bool) {
157        self.allow_memarg64 = allow;
158    }
159
160    /// Returns a range from the starting offset to the end of the buffer.
161    pub fn range(&self) -> Range<usize> {
162        self.original_offset..self.original_offset + self.buffer.len()
163    }
164
165    pub(crate) fn remaining_buffer(&self) -> &'a [u8] {
166        &self.buffer[self.position..]
167    }
168
169    fn ensure_has_byte(&self) -> Result<()> {
170        if self.position < self.buffer.len() {
171            Ok(())
172        } else {
173            Err(BinaryReaderError::eof(self.original_position(), 1))
174        }
175    }
176
177    pub(crate) fn ensure_has_bytes(&self, len: usize) -> Result<()> {
178        if self.position + len <= self.buffer.len() {
179            Ok(())
180        } else {
181            let hint = self.position + len - self.buffer.len();
182            Err(BinaryReaderError::eof(self.original_position(), hint))
183        }
184    }
185
186    /// Reads a value of type `T` from this binary reader, advancing the
187    /// internal position in this reader forward as data is read.
188    #[inline]
189    pub fn read<T>(&mut self) -> Result<T>
190    where
191        T: FromReader<'a>,
192    {
193        T::from_reader(self)
194    }
195
196    pub(crate) fn read_u7(&mut self) -> Result<u8> {
197        let b = self.read_u8()?;
198        if (b & 0x80) != 0 {
199            return Err(BinaryReaderError::new(
200                "invalid u7",
201                self.original_position() - 1,
202            ));
203        }
204        Ok(b)
205    }
206
207    pub(crate) fn external_kind_from_byte(byte: u8, offset: usize) -> Result<ExternalKind> {
208        match byte {
209            0x00 => Ok(ExternalKind::Func),
210            0x01 => Ok(ExternalKind::Table),
211            0x02 => Ok(ExternalKind::Memory),
212            0x03 => Ok(ExternalKind::Global),
213            0x04 => Ok(ExternalKind::Tag),
214            x => Err(Self::invalid_leading_byte_error(x, "external kind", offset)),
215        }
216    }
217
218    /// Reads a variable-length 32-bit size from the byte stream while checking
219    /// against a limit.
220    pub fn read_size(&mut self, limit: usize, desc: &str) -> Result<usize> {
221        let pos = self.original_position();
222        let size = self.read_var_u32()? as usize;
223        if size > limit {
224            bail!(pos, "{desc} size is out of bounds");
225        }
226        Ok(size)
227    }
228
229    /// Reads a variable-length 32-bit size from the byte stream while checking
230    /// against a limit.
231    ///
232    /// Then reads that many values of type `T` and returns them as an iterator.
233    ///
234    /// Note that regardless of how many items are read from the returned
235    /// iterator the items will still be parsed from this reader.
236    pub fn read_iter<'me, T>(
237        &'me mut self,
238        limit: usize,
239        desc: &str,
240    ) -> Result<BinaryReaderIter<'a, 'me, T>>
241    where
242        T: FromReader<'a>,
243    {
244        let size = self.read_size(limit, desc)?;
245        Ok(BinaryReaderIter {
246            remaining: size,
247            reader: self,
248            _marker: marker::PhantomData,
249        })
250    }
251
252    fn read_first_byte_and_var_u32(&mut self) -> Result<(u8, u32)> {
253        let pos = self.position;
254        let val = self.read_var_u32()?;
255        Ok((self.buffer[pos], val))
256    }
257
258    fn read_memarg(&mut self, max_align: u8) -> Result<MemArg> {
259        let flags_pos = self.original_position();
260        let mut flags = self.read_var_u32()?;
261        let memory = if flags & (1 << 6) != 0 {
262            flags ^= 1 << 6;
263            self.read_var_u32()?
264        } else {
265            0
266        };
267        let align = if flags >= (1 << 6) {
268            return Err(BinaryReaderError::new("alignment too large", flags_pos));
269        } else {
270            flags as u8
271        };
272        let offset = if self.allow_memarg64 {
273            self.read_var_u64()?
274        } else {
275            u64::from(self.read_var_u32()?)
276        };
277        Ok(MemArg {
278            align,
279            max_align,
280            offset,
281            memory,
282        })
283    }
284
285    fn read_br_table(&mut self) -> Result<BrTable<'a>> {
286        let cnt = self.read_size(MAX_WASM_BR_TABLE_SIZE, "br_table")?;
287        let start = self.position;
288        for _ in 0..cnt {
289            self.read_var_u32()?;
290        }
291        let end = self.position;
292        let default = self.read_var_u32()?;
293        Ok(BrTable {
294            reader: BinaryReader::new_with_offset(&self.buffer[start..end], start),
295            cnt: cnt as u32,
296            default,
297        })
298    }
299
300    /// Returns whether the `BinaryReader` has reached the end of the file.
301    #[inline]
302    pub fn eof(&self) -> bool {
303        self.position >= self.buffer.len()
304    }
305
306    /// Returns the `BinaryReader`'s current position.
307    #[inline]
308    pub fn current_position(&self) -> usize {
309        self.position
310    }
311
312    /// Returns the number of bytes remaining in the `BinaryReader`.
313    #[inline]
314    pub fn bytes_remaining(&self) -> usize {
315        self.buffer.len() - self.position
316    }
317
318    /// Advances the `BinaryReader` `size` bytes, and returns a slice from the
319    /// current position of `size` length.
320    ///
321    /// # Errors
322    /// If `size` exceeds the remaining length in `BinaryReader`.
323    pub fn read_bytes(&mut self, size: usize) -> Result<&'a [u8]> {
324        self.ensure_has_bytes(size)?;
325        let start = self.position;
326        self.position += size;
327        Ok(&self.buffer[start..self.position])
328    }
329
330    /// Reads a length-prefixed list of bytes from this reader and returns a
331    /// new `BinaryReader` to read that list of bytes.
332    ///
333    /// Advances the position of this reader by the number of bytes read.
334    pub fn read_reader(&mut self, err: &str) -> Result<BinaryReader<'a>> {
335        let size = self.read_var_u32()? as usize;
336        let body_start = self.position;
337        let buffer = match self.buffer.get(self.position..).and_then(|s| s.get(..size)) {
338            Some(buf) => buf,
339            None => {
340                return Err(BinaryReaderError::new(
341                    err,
342                    self.original_offset + self.buffer.len(),
343                ))
344            }
345        };
346        self.position += size;
347        Ok(BinaryReader::new_with_offset(
348            buffer,
349            self.original_offset + body_start,
350        ))
351    }
352
353    /// Advances the `BinaryReader` four bytes and returns a `u32`.
354    /// # Errors
355    /// If `BinaryReader` has less than four bytes remaining.
356    pub fn read_u32(&mut self) -> Result<u32> {
357        self.ensure_has_bytes(4)?;
358        let word = u32::from_le_bytes(
359            self.buffer[self.position..self.position + 4]
360                .try_into()
361                .unwrap(),
362        );
363        self.position += 4;
364        Ok(word)
365    }
366
367    /// Advances the `BinaryReader` eight bytes and returns a `u64`.
368    /// # Errors
369    /// If `BinaryReader` has less than eight bytes remaining.
370    pub fn read_u64(&mut self) -> Result<u64> {
371        self.ensure_has_bytes(8)?;
372        let word = u64::from_le_bytes(
373            self.buffer[self.position..self.position + 8]
374                .try_into()
375                .unwrap(),
376        );
377        self.position += 8;
378        Ok(word)
379    }
380
381    /// Advances the `BinaryReader` a single byte.
382    ///
383    /// # Errors
384    ///
385    /// If `BinaryReader` has no bytes remaining.
386    #[inline]
387    pub fn read_u8(&mut self) -> Result<u8> {
388        let b = match self.buffer.get(self.position) {
389            Some(b) => *b,
390            None => return Err(self.eof_err()),
391        };
392        self.position += 1;
393        Ok(b)
394    }
395
396    #[cold]
397    fn eof_err(&self) -> BinaryReaderError {
398        BinaryReaderError::eof(self.original_position(), 1)
399    }
400
401    /// Advances the `BinaryReader` up to four bytes to parse a variable
402    /// length integer as a `u32`.
403    ///
404    /// # Errors
405    ///
406    /// If `BinaryReader` has less than one or up to four bytes remaining, or
407    /// the integer is larger than 32 bits.
408    #[inline]
409    pub fn read_var_u32(&mut self) -> Result<u32> {
410        // Optimization for single byte i32.
411        let byte = self.read_u8()?;
412        if (byte & 0x80) == 0 {
413            Ok(u32::from(byte))
414        } else {
415            self.read_var_u32_big(byte)
416        }
417    }
418
419    fn read_var_u32_big(&mut self, byte: u8) -> Result<u32> {
420        let mut result = (byte & 0x7F) as u32;
421        let mut shift = 7;
422        loop {
423            let byte = self.read_u8()?;
424            result |= ((byte & 0x7F) as u32) << shift;
425            if shift >= 25 && (byte >> (32 - shift)) != 0 {
426                let msg = if byte & 0x80 != 0 {
427                    "invalid var_u32: integer representation too long"
428                } else {
429                    "invalid var_u32: integer too large"
430                };
431                // The continuation bit or unused bits are set.
432                return Err(BinaryReaderError::new(msg, self.original_position() - 1));
433            }
434            shift += 7;
435            if (byte & 0x80) == 0 {
436                break;
437            }
438        }
439        Ok(result)
440    }
441
442    /// Advances the `BinaryReader` up to four bytes to parse a variable
443    /// length integer as a `u64`.
444    ///
445    /// # Errors
446    ///
447    /// If `BinaryReader` has less than one or up to eight bytes remaining, or
448    /// the integer is larger than 64 bits.
449    #[inline]
450    pub fn read_var_u64(&mut self) -> Result<u64> {
451        // Optimization for single byte u64.
452        let byte = u64::from(self.read_u8()?);
453        if (byte & 0x80) == 0 {
454            Ok(byte)
455        } else {
456            self.read_var_u64_big(byte)
457        }
458    }
459
460    fn read_var_u64_big(&mut self, byte: u64) -> Result<u64> {
461        let mut result = byte & 0x7F;
462        let mut shift = 7;
463        loop {
464            let byte = u64::from(self.read_u8()?);
465            result |= (byte & 0x7F) << shift;
466            if shift >= 57 && (byte >> (64 - shift)) != 0 {
467                let msg = if byte & 0x80 != 0 {
468                    "invalid var_u64: integer representation too long"
469                } else {
470                    "invalid var_u64: integer too large"
471                };
472                // The continuation bit or unused bits are set.
473                return Err(BinaryReaderError::new(msg, self.original_position() - 1));
474            }
475            shift += 7;
476            if (byte & 0x80) == 0 {
477                break;
478            }
479        }
480        Ok(result)
481    }
482
483    /// Executes `f` to skip some data in this binary reader and then returns a
484    /// reader which will read the skipped data.
485    pub fn skip(&mut self, f: impl FnOnce(&mut Self) -> Result<()>) -> Result<Self> {
486        let start = self.position;
487        f(self)?;
488        Ok(BinaryReader::new_with_offset(
489            &self.buffer[start..self.position],
490            self.original_offset + start,
491        ))
492    }
493
494    /// Advances the `BinaryReader` past a WebAssembly string. This method does
495    /// not perform any utf-8 validation.
496    /// # Errors
497    /// If `BinaryReader` has less than four bytes, the string's length exceeds
498    /// the remaining bytes, or the string length
499    /// exceeds `limits::MAX_WASM_STRING_SIZE`.
500    pub fn skip_string(&mut self) -> Result<()> {
501        let len = self.read_var_u32()? as usize;
502        if len > MAX_WASM_STRING_SIZE {
503            return Err(BinaryReaderError::new(
504                "string size out of bounds",
505                self.original_position() - 1,
506            ));
507        }
508        self.ensure_has_bytes(len)?;
509        self.position += len;
510        Ok(())
511    }
512
513    /// Advances the `BinaryReader` up to four bytes to parse a variable
514    /// length integer as a `i32`.
515    /// # Errors
516    /// If `BinaryReader` has less than one or up to four bytes remaining, or
517    /// the integer is larger than 32 bits.
518    #[inline]
519    pub fn read_var_i32(&mut self) -> Result<i32> {
520        // Optimization for single byte i32.
521        let byte = self.read_u8()?;
522        if (byte & 0x80) == 0 {
523            Ok(((byte as i32) << 25) >> 25)
524        } else {
525            self.read_var_i32_big(byte)
526        }
527    }
528
529    fn read_var_i32_big(&mut self, byte: u8) -> Result<i32> {
530        let mut result = (byte & 0x7F) as i32;
531        let mut shift = 7;
532        loop {
533            let byte = self.read_u8()?;
534            result |= ((byte & 0x7F) as i32) << shift;
535            if shift >= 25 {
536                let continuation_bit = (byte & 0x80) != 0;
537                let sign_and_unused_bit = (byte << 1) as i8 >> (32 - shift);
538                if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
539                    let msg = if continuation_bit {
540                        "invalid var_i32: integer representation too long"
541                    } else {
542                        "invalid var_i32: integer too large"
543                    };
544                    return Err(BinaryReaderError::new(msg, self.original_position() - 1));
545                }
546                return Ok(result);
547            }
548            shift += 7;
549            if (byte & 0x80) == 0 {
550                break;
551            }
552        }
553        let ashift = 32 - shift;
554        Ok((result << ashift) >> ashift)
555    }
556
557    /// Advances the `BinaryReader` up to four bytes to parse a variable
558    /// length integer as a signed 33 bit integer, returned as a `i64`.
559    /// # Errors
560    /// If `BinaryReader` has less than one or up to five bytes remaining, or
561    /// the integer is larger than 33 bits.
562    pub fn read_var_s33(&mut self) -> Result<i64> {
563        // Optimization for single byte.
564        let byte = self.read_u8()?;
565        if (byte & 0x80) == 0 {
566            return Ok(((byte as i8) << 1) as i64 >> 1);
567        }
568
569        let mut result = (byte & 0x7F) as i64;
570        let mut shift = 7;
571        loop {
572            let byte = self.read_u8()?;
573            result |= ((byte & 0x7F) as i64) << shift;
574            if shift >= 25 {
575                let continuation_bit = (byte & 0x80) != 0;
576                let sign_and_unused_bit = (byte << 1) as i8 >> (33 - shift);
577                if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
578                    return Err(BinaryReaderError::new(
579                        "invalid var_s33: integer representation too long",
580                        self.original_position() - 1,
581                    ));
582                }
583                return Ok(result);
584            }
585            shift += 7;
586            if (byte & 0x80) == 0 {
587                break;
588            }
589        }
590        let ashift = 64 - shift;
591        Ok((result << ashift) >> ashift)
592    }
593
594    /// Advances the `BinaryReader` up to eight bytes to parse a variable
595    /// length integer as a 64 bit integer, returned as a `i64`.
596    /// # Errors
597    /// If `BinaryReader` has less than one or up to eight bytes remaining, or
598    /// the integer is larger than 64 bits.
599    pub fn read_var_i64(&mut self) -> Result<i64> {
600        let mut result: i64 = 0;
601        let mut shift = 0;
602        loop {
603            let byte = self.read_u8()?;
604            result |= i64::from(byte & 0x7F) << shift;
605            if shift >= 57 {
606                let continuation_bit = (byte & 0x80) != 0;
607                let sign_and_unused_bit = ((byte << 1) as i8) >> (64 - shift);
608                if continuation_bit || (sign_and_unused_bit != 0 && sign_and_unused_bit != -1) {
609                    let msg = if continuation_bit {
610                        "invalid var_i64: integer representation too long"
611                    } else {
612                        "invalid var_i64: integer too large"
613                    };
614                    return Err(BinaryReaderError::new(msg, self.original_position() - 1));
615                }
616                return Ok(result);
617            }
618            shift += 7;
619            if (byte & 0x80) == 0 {
620                break;
621            }
622        }
623        let ashift = 64 - shift;
624        Ok((result << ashift) >> ashift)
625    }
626
627    /// Advances the `BinaryReader` up to four bytes to parse a variable
628    /// length integer as a 32 bit floating point integer, returned as `Ieee32`.
629    /// # Errors
630    /// If `BinaryReader` has less than one or up to four bytes remaining, or
631    /// the integer is larger than 32 bits.
632    pub fn read_f32(&mut self) -> Result<Ieee32> {
633        let value = self.read_u32()?;
634        Ok(Ieee32(value))
635    }
636
637    /// Advances the `BinaryReader` up to four bytes to parse a variable
638    /// length integer as a 32 bit floating point integer, returned as `Ieee32`.
639    /// # Errors
640    /// If `BinaryReader` has less than one or up to four bytes remaining, or
641    /// the integer is larger than 32 bits.
642    pub fn read_f64(&mut self) -> Result<Ieee64> {
643        let value = self.read_u64()?;
644        Ok(Ieee64(value))
645    }
646
647    /// Reads a WebAssembly string from the module.
648    /// # Errors
649    /// If `BinaryReader` has less than up to four bytes remaining, the string's
650    /// length exceeds the remaining bytes, the string's length exceeds
651    /// `limits::MAX_WASM_STRING_SIZE`, or the string contains invalid utf-8.
652    pub fn read_string(&mut self) -> Result<&'a str> {
653        let len = self.read_var_u32()? as usize;
654        if len > MAX_WASM_STRING_SIZE {
655            return Err(BinaryReaderError::new(
656                "string size out of bounds",
657                self.original_position() - 1,
658            ));
659        }
660        let bytes = self.read_bytes(len)?;
661        str::from_utf8(bytes).map_err(|_| {
662            BinaryReaderError::new("invalid UTF-8 encoding", self.original_position() - 1)
663        })
664    }
665
666    #[cold]
667    pub(crate) fn invalid_leading_byte<T>(&self, byte: u8, desc: &str) -> Result<T> {
668        Err(Self::invalid_leading_byte_error(
669            byte,
670            desc,
671            self.original_position() - 1,
672        ))
673    }
674
675    pub(crate) fn invalid_leading_byte_error(
676        byte: u8,
677        desc: &str,
678        offset: usize,
679    ) -> BinaryReaderError {
680        format_err!(offset, "invalid leading byte (0x{byte:x}) for {desc}")
681    }
682
683    pub(crate) fn peek(&self) -> Result<u8> {
684        self.ensure_has_byte()?;
685        Ok(self.buffer[self.position])
686    }
687
688    pub(crate) fn read_block_type(&mut self) -> Result<BlockType> {
689        let b = self.peek()?;
690
691        // Check for empty block
692        if b == 0x40 {
693            self.position += 1;
694            return Ok(BlockType::Empty);
695        }
696
697        // Check for a block type of form [] -> [t].
698        if ValType::is_valtype_byte(b) {
699            return Ok(BlockType::Type(self.read()?));
700        }
701
702        // Not empty or a singular type, so read the function type index
703        let idx = self.read_var_s33()?;
704        match u32::try_from(idx) {
705            Ok(idx) => Ok(BlockType::FuncType(idx)),
706            Err(_) => {
707                return Err(BinaryReaderError::new(
708                    "invalid function type",
709                    self.original_position(),
710                ));
711            }
712        }
713    }
714
715    /// Visit the next available operator with the specified [`VisitOperator`] instance.
716    ///
717    /// Note that this does not implicitly propagate any additional information such as instruction
718    /// offsets. In order to do so, consider storing such data within the visitor before visiting.
719    ///
720    /// # Errors
721    ///
722    /// If `BinaryReader` has less bytes remaining than required to parse the `Operator`.
723    ///
724    /// # Examples
725    ///
726    /// Store an offset for use in diagnostics or any other purposes:
727    ///
728    /// ```
729    /// # use tinywasm_wasmparser::{BinaryReader, VisitOperator, Result, for_each_operator};
730    ///
731    /// pub fn dump(mut reader: BinaryReader) -> Result<()> {
732    ///     let mut visitor = Dumper { offset: 0 };
733    ///     while !reader.eof() {
734    ///         visitor.offset = reader.original_position();
735    ///         reader.visit_operator(&mut visitor)?;
736    ///     }
737    ///     Ok(())
738    /// }
739    ///
740    /// struct Dumper {
741    ///     offset: usize
742    /// }
743    ///
744    /// macro_rules! define_visit_operator {
745    ///     ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
746    ///         $(
747    ///             fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
748    ///                 println!("{}: {}", self.offset, stringify!($visit));
749    ///             }
750    ///         )*
751    ///     }
752    /// }
753    ///
754    /// impl<'a> VisitOperator<'a> for Dumper {
755    ///     type Output = ();
756    ///     for_each_operator!(define_visit_operator);
757    /// }
758    ///
759    /// ```
760    pub fn visit_operator<T>(&mut self, visitor: &mut T) -> Result<<T as VisitOperator<'a>>::Output>
761    where
762        T: VisitOperator<'a>,
763    {
764        let pos = self.original_position();
765        let code = self.read_u8()? as u8;
766        Ok(match code {
767            0x00 => visitor.visit_unreachable(),
768            0x01 => visitor.visit_nop(),
769            0x02 => visitor.visit_block(self.read_block_type()?),
770            0x03 => visitor.visit_loop(self.read_block_type()?),
771            0x04 => visitor.visit_if(self.read_block_type()?),
772            0x05 => visitor.visit_else(),
773            0x06 => visitor.visit_try(self.read_block_type()?),
774            0x07 => visitor.visit_catch(self.read_var_u32()?),
775            0x08 => visitor.visit_throw(self.read_var_u32()?),
776            0x09 => visitor.visit_rethrow(self.read_var_u32()?),
777            0x0a => visitor.visit_throw_ref(),
778            0x0b => visitor.visit_end(),
779            0x0c => visitor.visit_br(self.read_var_u32()?),
780            0x0d => visitor.visit_br_if(self.read_var_u32()?),
781            0x0e => visitor.visit_br_table(self.read_br_table()?),
782            0x0f => visitor.visit_return(),
783            0x10 => visitor.visit_call(self.read_var_u32()?),
784            0x11 => {
785                let index = self.read_var_u32()?;
786                let (table_byte, table_index) = self.read_first_byte_and_var_u32()?;
787                visitor.visit_call_indirect(index, table_index, table_byte)
788            }
789            0x12 => visitor.visit_return_call(self.read_var_u32()?),
790            0x13 => visitor.visit_return_call_indirect(self.read_var_u32()?, self.read_var_u32()?),
791            0x14 => visitor.visit_call_ref(self.read()?),
792            0x15 => visitor.visit_return_call_ref(self.read()?),
793            0x18 => visitor.visit_delegate(self.read_var_u32()?),
794            0x19 => visitor.visit_catch_all(),
795            0x1a => visitor.visit_drop(),
796            0x1b => visitor.visit_select(),
797            0x1c => {
798                let results = self.read_var_u32()?;
799                if results != 1 {
800                    return Err(BinaryReaderError::new(
801                        "invalid result arity",
802                        self.position,
803                    ));
804                }
805                visitor.visit_typed_select(self.read()?)
806            }
807            0x1f => visitor.visit_try_table(self.read()?),
808
809            0x20 => visitor.visit_local_get(self.read_var_u32()?),
810            0x21 => visitor.visit_local_set(self.read_var_u32()?),
811            0x22 => visitor.visit_local_tee(self.read_var_u32()?),
812            0x23 => visitor.visit_global_get(self.read_var_u32()?),
813            0x24 => visitor.visit_global_set(self.read_var_u32()?),
814            0x25 => visitor.visit_table_get(self.read_var_u32()?),
815            0x26 => visitor.visit_table_set(self.read_var_u32()?),
816
817            0x28 => visitor.visit_i32_load(self.read_memarg(2)?),
818            0x29 => visitor.visit_i64_load(self.read_memarg(3)?),
819            0x2a => visitor.visit_f32_load(self.read_memarg(2)?),
820            0x2b => visitor.visit_f64_load(self.read_memarg(3)?),
821            0x2c => visitor.visit_i32_load8_s(self.read_memarg(0)?),
822            0x2d => visitor.visit_i32_load8_u(self.read_memarg(0)?),
823            0x2e => visitor.visit_i32_load16_s(self.read_memarg(1)?),
824            0x2f => visitor.visit_i32_load16_u(self.read_memarg(1)?),
825            0x30 => visitor.visit_i64_load8_s(self.read_memarg(0)?),
826            0x31 => visitor.visit_i64_load8_u(self.read_memarg(0)?),
827            0x32 => visitor.visit_i64_load16_s(self.read_memarg(1)?),
828            0x33 => visitor.visit_i64_load16_u(self.read_memarg(1)?),
829            0x34 => visitor.visit_i64_load32_s(self.read_memarg(2)?),
830            0x35 => visitor.visit_i64_load32_u(self.read_memarg(2)?),
831            0x36 => visitor.visit_i32_store(self.read_memarg(2)?),
832            0x37 => visitor.visit_i64_store(self.read_memarg(3)?),
833            0x38 => visitor.visit_f32_store(self.read_memarg(2)?),
834            0x39 => visitor.visit_f64_store(self.read_memarg(3)?),
835            0x3a => visitor.visit_i32_store8(self.read_memarg(0)?),
836            0x3b => visitor.visit_i32_store16(self.read_memarg(1)?),
837            0x3c => visitor.visit_i64_store8(self.read_memarg(0)?),
838            0x3d => visitor.visit_i64_store16(self.read_memarg(1)?),
839            0x3e => visitor.visit_i64_store32(self.read_memarg(2)?),
840            0x3f => {
841                let (mem_byte, mem) = self.read_first_byte_and_var_u32()?;
842                visitor.visit_memory_size(mem, mem_byte)
843            }
844            0x40 => {
845                let (mem_byte, mem) = self.read_first_byte_and_var_u32()?;
846                visitor.visit_memory_grow(mem, mem_byte)
847            }
848
849            0x41 => visitor.visit_i32_const(self.read_var_i32()?),
850            0x42 => visitor.visit_i64_const(self.read_var_i64()?),
851            0x43 => visitor.visit_f32_const(self.read_f32()?),
852            0x44 => visitor.visit_f64_const(self.read_f64()?),
853
854            0x45 => visitor.visit_i32_eqz(),
855            0x46 => visitor.visit_i32_eq(),
856            0x47 => visitor.visit_i32_ne(),
857            0x48 => visitor.visit_i32_lt_s(),
858            0x49 => visitor.visit_i32_lt_u(),
859            0x4a => visitor.visit_i32_gt_s(),
860            0x4b => visitor.visit_i32_gt_u(),
861            0x4c => visitor.visit_i32_le_s(),
862            0x4d => visitor.visit_i32_le_u(),
863            0x4e => visitor.visit_i32_ge_s(),
864            0x4f => visitor.visit_i32_ge_u(),
865            0x50 => visitor.visit_i64_eqz(),
866            0x51 => visitor.visit_i64_eq(),
867            0x52 => visitor.visit_i64_ne(),
868            0x53 => visitor.visit_i64_lt_s(),
869            0x54 => visitor.visit_i64_lt_u(),
870            0x55 => visitor.visit_i64_gt_s(),
871            0x56 => visitor.visit_i64_gt_u(),
872            0x57 => visitor.visit_i64_le_s(),
873            0x58 => visitor.visit_i64_le_u(),
874            0x59 => visitor.visit_i64_ge_s(),
875            0x5a => visitor.visit_i64_ge_u(),
876            0x5b => visitor.visit_f32_eq(),
877            0x5c => visitor.visit_f32_ne(),
878            0x5d => visitor.visit_f32_lt(),
879            0x5e => visitor.visit_f32_gt(),
880            0x5f => visitor.visit_f32_le(),
881            0x60 => visitor.visit_f32_ge(),
882            0x61 => visitor.visit_f64_eq(),
883            0x62 => visitor.visit_f64_ne(),
884            0x63 => visitor.visit_f64_lt(),
885            0x64 => visitor.visit_f64_gt(),
886            0x65 => visitor.visit_f64_le(),
887            0x66 => visitor.visit_f64_ge(),
888            0x67 => visitor.visit_i32_clz(),
889            0x68 => visitor.visit_i32_ctz(),
890            0x69 => visitor.visit_i32_popcnt(),
891            0x6a => visitor.visit_i32_add(),
892            0x6b => visitor.visit_i32_sub(),
893            0x6c => visitor.visit_i32_mul(),
894            0x6d => visitor.visit_i32_div_s(),
895            0x6e => visitor.visit_i32_div_u(),
896            0x6f => visitor.visit_i32_rem_s(),
897            0x70 => visitor.visit_i32_rem_u(),
898            0x71 => visitor.visit_i32_and(),
899            0x72 => visitor.visit_i32_or(),
900            0x73 => visitor.visit_i32_xor(),
901            0x74 => visitor.visit_i32_shl(),
902            0x75 => visitor.visit_i32_shr_s(),
903            0x76 => visitor.visit_i32_shr_u(),
904            0x77 => visitor.visit_i32_rotl(),
905            0x78 => visitor.visit_i32_rotr(),
906            0x79 => visitor.visit_i64_clz(),
907            0x7a => visitor.visit_i64_ctz(),
908            0x7b => visitor.visit_i64_popcnt(),
909            0x7c => visitor.visit_i64_add(),
910            0x7d => visitor.visit_i64_sub(),
911            0x7e => visitor.visit_i64_mul(),
912            0x7f => visitor.visit_i64_div_s(),
913            0x80 => visitor.visit_i64_div_u(),
914            0x81 => visitor.visit_i64_rem_s(),
915            0x82 => visitor.visit_i64_rem_u(),
916            0x83 => visitor.visit_i64_and(),
917            0x84 => visitor.visit_i64_or(),
918            0x85 => visitor.visit_i64_xor(),
919            0x86 => visitor.visit_i64_shl(),
920            0x87 => visitor.visit_i64_shr_s(),
921            0x88 => visitor.visit_i64_shr_u(),
922            0x89 => visitor.visit_i64_rotl(),
923            0x8a => visitor.visit_i64_rotr(),
924            0x8b => visitor.visit_f32_abs(),
925            0x8c => visitor.visit_f32_neg(),
926            0x8d => visitor.visit_f32_ceil(),
927            0x8e => visitor.visit_f32_floor(),
928            0x8f => visitor.visit_f32_trunc(),
929            0x90 => visitor.visit_f32_nearest(),
930            0x91 => visitor.visit_f32_sqrt(),
931            0x92 => visitor.visit_f32_add(),
932            0x93 => visitor.visit_f32_sub(),
933            0x94 => visitor.visit_f32_mul(),
934            0x95 => visitor.visit_f32_div(),
935            0x96 => visitor.visit_f32_min(),
936            0x97 => visitor.visit_f32_max(),
937            0x98 => visitor.visit_f32_copysign(),
938            0x99 => visitor.visit_f64_abs(),
939            0x9a => visitor.visit_f64_neg(),
940            0x9b => visitor.visit_f64_ceil(),
941            0x9c => visitor.visit_f64_floor(),
942            0x9d => visitor.visit_f64_trunc(),
943            0x9e => visitor.visit_f64_nearest(),
944            0x9f => visitor.visit_f64_sqrt(),
945            0xa0 => visitor.visit_f64_add(),
946            0xa1 => visitor.visit_f64_sub(),
947            0xa2 => visitor.visit_f64_mul(),
948            0xa3 => visitor.visit_f64_div(),
949            0xa4 => visitor.visit_f64_min(),
950            0xa5 => visitor.visit_f64_max(),
951            0xa6 => visitor.visit_f64_copysign(),
952            0xa7 => visitor.visit_i32_wrap_i64(),
953            0xa8 => visitor.visit_i32_trunc_f32_s(),
954            0xa9 => visitor.visit_i32_trunc_f32_u(),
955            0xaa => visitor.visit_i32_trunc_f64_s(),
956            0xab => visitor.visit_i32_trunc_f64_u(),
957            0xac => visitor.visit_i64_extend_i32_s(),
958            0xad => visitor.visit_i64_extend_i32_u(),
959            0xae => visitor.visit_i64_trunc_f32_s(),
960            0xaf => visitor.visit_i64_trunc_f32_u(),
961            0xb0 => visitor.visit_i64_trunc_f64_s(),
962            0xb1 => visitor.visit_i64_trunc_f64_u(),
963            0xb2 => visitor.visit_f32_convert_i32_s(),
964            0xb3 => visitor.visit_f32_convert_i32_u(),
965            0xb4 => visitor.visit_f32_convert_i64_s(),
966            0xb5 => visitor.visit_f32_convert_i64_u(),
967            0xb6 => visitor.visit_f32_demote_f64(),
968            0xb7 => visitor.visit_f64_convert_i32_s(),
969            0xb8 => visitor.visit_f64_convert_i32_u(),
970            0xb9 => visitor.visit_f64_convert_i64_s(),
971            0xba => visitor.visit_f64_convert_i64_u(),
972            0xbb => visitor.visit_f64_promote_f32(),
973            0xbc => visitor.visit_i32_reinterpret_f32(),
974            0xbd => visitor.visit_i64_reinterpret_f64(),
975            0xbe => visitor.visit_f32_reinterpret_i32(),
976            0xbf => visitor.visit_f64_reinterpret_i64(),
977
978            0xc0 => visitor.visit_i32_extend8_s(),
979            0xc1 => visitor.visit_i32_extend16_s(),
980            0xc2 => visitor.visit_i64_extend8_s(),
981            0xc3 => visitor.visit_i64_extend16_s(),
982            0xc4 => visitor.visit_i64_extend32_s(),
983
984            0xd0 => visitor.visit_ref_null(self.read()?),
985            0xd1 => visitor.visit_ref_is_null(),
986            0xd2 => visitor.visit_ref_func(self.read_var_u32()?),
987            0xd3 => visitor.visit_ref_eq(),
988            0xd4 => visitor.visit_ref_as_non_null(),
989            0xd5 => visitor.visit_br_on_null(self.read_var_u32()?),
990            0xd6 => visitor.visit_br_on_non_null(self.read_var_u32()?),
991
992            0xfb => self.visit_0xfb_operator(pos, visitor)?,
993            0xfc => self.visit_0xfc_operator(pos, visitor)?,
994            0xfd => self.visit_0xfd_operator(pos, visitor)?,
995            0xfe => self.visit_0xfe_operator(pos, visitor)?,
996
997            _ => bail!(pos, "illegal opcode: 0x{code:x}"),
998        })
999    }
1000
1001    fn visit_0xfb_operator<T>(
1002        &mut self,
1003        pos: usize,
1004        visitor: &mut T,
1005    ) -> Result<<T as VisitOperator<'a>>::Output>
1006    where
1007        T: VisitOperator<'a>,
1008    {
1009        let code = self.read_var_u32()?;
1010        Ok(match code {
1011            0x0 => {
1012                let type_index = self.read_var_u32()?;
1013                visitor.visit_struct_new(type_index)
1014            }
1015            0x01 => {
1016                let type_index = self.read_var_u32()?;
1017                visitor.visit_struct_new_default(type_index)
1018            }
1019            0x02 => {
1020                let type_index = self.read_var_u32()?;
1021                let field_index = self.read_var_u32()?;
1022                visitor.visit_struct_get(type_index, field_index)
1023            }
1024            0x03 => {
1025                let type_index = self.read_var_u32()?;
1026                let field_index = self.read_var_u32()?;
1027                visitor.visit_struct_get_s(type_index, field_index)
1028            }
1029            0x04 => {
1030                let type_index = self.read_var_u32()?;
1031                let field_index = self.read_var_u32()?;
1032                visitor.visit_struct_get_u(type_index, field_index)
1033            }
1034            0x05 => {
1035                let type_index = self.read_var_u32()?;
1036                let field_index = self.read_var_u32()?;
1037                visitor.visit_struct_set(type_index, field_index)
1038            }
1039            0x06 => {
1040                let type_index = self.read_var_u32()?;
1041                visitor.visit_array_new(type_index)
1042            }
1043            0x07 => {
1044                let type_index = self.read_var_u32()?;
1045                visitor.visit_array_new_default(type_index)
1046            }
1047            0x08 => {
1048                let type_index = self.read_var_u32()?;
1049                let n = self.read_var_u32()?;
1050                visitor.visit_array_new_fixed(type_index, n)
1051            }
1052            0x09 => {
1053                let type_index = self.read_var_u32()?;
1054                let data_index = self.read_var_u32()?;
1055                visitor.visit_array_new_data(type_index, data_index)
1056            }
1057            0x0a => {
1058                let type_index = self.read_var_u32()?;
1059                let elem_index = self.read_var_u32()?;
1060                visitor.visit_array_new_elem(type_index, elem_index)
1061            }
1062            0x0b => {
1063                let type_index = self.read_var_u32()?;
1064                visitor.visit_array_get(type_index)
1065            }
1066            0x0c => {
1067                let type_index = self.read_var_u32()?;
1068                visitor.visit_array_get_s(type_index)
1069            }
1070            0x0d => {
1071                let type_index = self.read_var_u32()?;
1072                visitor.visit_array_get_u(type_index)
1073            }
1074            0x0e => {
1075                let type_index = self.read_var_u32()?;
1076                visitor.visit_array_set(type_index)
1077            }
1078            0x0f => visitor.visit_array_len(),
1079            0x10 => {
1080                let type_index = self.read_var_u32()?;
1081                visitor.visit_array_fill(type_index)
1082            }
1083            0x11 => {
1084                let type_index_dst = self.read_var_u32()?;
1085                let type_index_src = self.read_var_u32()?;
1086                visitor.visit_array_copy(type_index_dst, type_index_src)
1087            }
1088            0x12 => {
1089                let type_index = self.read_var_u32()?;
1090                let data_index = self.read_var_u32()?;
1091                visitor.visit_array_init_data(type_index, data_index)
1092            }
1093            0x13 => {
1094                let type_index = self.read_var_u32()?;
1095                let elem_index = self.read_var_u32()?;
1096                visitor.visit_array_init_elem(type_index, elem_index)
1097            }
1098            0x14 => visitor.visit_ref_test_non_null(self.read()?),
1099            0x15 => visitor.visit_ref_test_nullable(self.read()?),
1100            0x16 => visitor.visit_ref_cast_non_null(self.read()?),
1101            0x17 => visitor.visit_ref_cast_nullable(self.read()?),
1102            0x18 => {
1103                let pos = self.original_position();
1104                let cast_flags = self.read_u8()?;
1105                let relative_depth = self.read_var_u32()?;
1106                let (from_type_nullable, to_type_nullable) = match cast_flags {
1107                    0b00 => (false, false),
1108                    0b01 => (true, false),
1109                    0b10 => (false, true),
1110                    0b11 => (true, true),
1111                    _ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1112                };
1113                let from_heap_type = self.read()?;
1114                let from_ref_type =
1115                    RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1116                        format_err!(pos, "implementation error: type index too large")
1117                    })?;
1118                let to_heap_type = self.read()?;
1119                let to_ref_type =
1120                    RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1121                        format_err!(pos, "implementation error: type index too large")
1122                    })?;
1123                visitor.visit_br_on_cast(relative_depth, from_ref_type, to_ref_type)
1124            }
1125            0x19 => {
1126                let pos = self.original_position();
1127                let cast_flags = self.read_u8()?;
1128                let relative_depth = self.read_var_u32()?;
1129                let (from_type_nullable, to_type_nullable) = match cast_flags {
1130                    0 => (false, false),
1131                    1 => (true, false),
1132                    2 => (false, true),
1133                    3 => (true, true),
1134                    _ => bail!(pos, "invalid cast flags: {cast_flags:08b}"),
1135                };
1136                let from_heap_type = self.read()?;
1137                let from_ref_type =
1138                    RefType::new(from_type_nullable, from_heap_type).ok_or_else(|| {
1139                        format_err!(pos, "implementation error: type index too large")
1140                    })?;
1141                let to_heap_type = self.read()?;
1142                let to_ref_type =
1143                    RefType::new(to_type_nullable, to_heap_type).ok_or_else(|| {
1144                        format_err!(pos, "implementation error: type index too large")
1145                    })?;
1146                visitor.visit_br_on_cast_fail(relative_depth, from_ref_type, to_ref_type)
1147            }
1148
1149            0x1a => visitor.visit_any_convert_extern(),
1150            0x1b => visitor.visit_extern_convert_any(),
1151
1152            0x1c => visitor.visit_ref_i31(),
1153            0x1d => visitor.visit_i31_get_s(),
1154            0x1e => visitor.visit_i31_get_u(),
1155
1156            _ => bail!(pos, "unknown 0xfb subopcode: 0x{code:x}"),
1157        })
1158    }
1159
1160    fn visit_0xfc_operator<T>(
1161        &mut self,
1162        pos: usize,
1163        visitor: &mut T,
1164    ) -> Result<<T as VisitOperator<'a>>::Output>
1165    where
1166        T: VisitOperator<'a>,
1167    {
1168        let code = self.read_var_u32()?;
1169        Ok(match code {
1170            0x00 => visitor.visit_i32_trunc_sat_f32_s(),
1171            0x01 => visitor.visit_i32_trunc_sat_f32_u(),
1172            0x02 => visitor.visit_i32_trunc_sat_f64_s(),
1173            0x03 => visitor.visit_i32_trunc_sat_f64_u(),
1174            0x04 => visitor.visit_i64_trunc_sat_f32_s(),
1175            0x05 => visitor.visit_i64_trunc_sat_f32_u(),
1176            0x06 => visitor.visit_i64_trunc_sat_f64_s(),
1177            0x07 => visitor.visit_i64_trunc_sat_f64_u(),
1178
1179            0x08 => {
1180                let segment = self.read_var_u32()?;
1181                let mem = self.read_var_u32()?;
1182                visitor.visit_memory_init(segment, mem)
1183            }
1184            0x09 => {
1185                let segment = self.read_var_u32()?;
1186                visitor.visit_data_drop(segment)
1187            }
1188            0x0a => {
1189                let dst = self.read_var_u32()?;
1190                let src = self.read_var_u32()?;
1191                visitor.visit_memory_copy(dst, src)
1192            }
1193            0x0b => {
1194                let mem = self.read_var_u32()?;
1195                visitor.visit_memory_fill(mem)
1196            }
1197            0x0c => {
1198                let segment = self.read_var_u32()?;
1199                let table = self.read_var_u32()?;
1200                visitor.visit_table_init(segment, table)
1201            }
1202            0x0d => {
1203                let segment = self.read_var_u32()?;
1204                visitor.visit_elem_drop(segment)
1205            }
1206            0x0e => {
1207                let dst_table = self.read_var_u32()?;
1208                let src_table = self.read_var_u32()?;
1209                visitor.visit_table_copy(dst_table, src_table)
1210            }
1211
1212            0x0f => {
1213                let table = self.read_var_u32()?;
1214                visitor.visit_table_grow(table)
1215            }
1216            0x10 => {
1217                let table = self.read_var_u32()?;
1218                visitor.visit_table_size(table)
1219            }
1220
1221            0x11 => {
1222                let table = self.read_var_u32()?;
1223                visitor.visit_table_fill(table)
1224            }
1225
1226            0x12 => {
1227                let mem = self.read_var_u32()?;
1228                visitor.visit_memory_discard(mem)
1229            }
1230
1231            _ => bail!(pos, "unknown 0xfc subopcode: 0x{code:x}"),
1232        })
1233    }
1234
1235    fn visit_0xfd_operator<T>(
1236        &mut self,
1237        pos: usize,
1238        visitor: &mut T,
1239    ) -> Result<<T as VisitOperator<'a>>::Output>
1240    where
1241        T: VisitOperator<'a>,
1242    {
1243        let code = self.read_var_u32()?;
1244        Ok(match code {
1245            0x00 => visitor.visit_v128_load(self.read_memarg(4)?),
1246            0x01 => visitor.visit_v128_load8x8_s(self.read_memarg(3)?),
1247            0x02 => visitor.visit_v128_load8x8_u(self.read_memarg(3)?),
1248            0x03 => visitor.visit_v128_load16x4_s(self.read_memarg(3)?),
1249            0x04 => visitor.visit_v128_load16x4_u(self.read_memarg(3)?),
1250            0x05 => visitor.visit_v128_load32x2_s(self.read_memarg(3)?),
1251            0x06 => visitor.visit_v128_load32x2_u(self.read_memarg(3)?),
1252            0x07 => visitor.visit_v128_load8_splat(self.read_memarg(0)?),
1253            0x08 => visitor.visit_v128_load16_splat(self.read_memarg(1)?),
1254            0x09 => visitor.visit_v128_load32_splat(self.read_memarg(2)?),
1255            0x0a => visitor.visit_v128_load64_splat(self.read_memarg(3)?),
1256
1257            0x0b => visitor.visit_v128_store(self.read_memarg(4)?),
1258            0x0c => visitor.visit_v128_const(self.read_v128()?),
1259            0x0d => {
1260                let mut lanes: [u8; 16] = [0; 16];
1261                for lane in &mut lanes {
1262                    *lane = self.read_lane_index(32)?
1263                }
1264                visitor.visit_i8x16_shuffle(lanes)
1265            }
1266
1267            0x0e => visitor.visit_i8x16_swizzle(),
1268            0x0f => visitor.visit_i8x16_splat(),
1269            0x10 => visitor.visit_i16x8_splat(),
1270            0x11 => visitor.visit_i32x4_splat(),
1271            0x12 => visitor.visit_i64x2_splat(),
1272            0x13 => visitor.visit_f32x4_splat(),
1273            0x14 => visitor.visit_f64x2_splat(),
1274
1275            0x15 => visitor.visit_i8x16_extract_lane_s(self.read_lane_index(16)?),
1276            0x16 => visitor.visit_i8x16_extract_lane_u(self.read_lane_index(16)?),
1277            0x17 => visitor.visit_i8x16_replace_lane(self.read_lane_index(16)?),
1278            0x18 => visitor.visit_i16x8_extract_lane_s(self.read_lane_index(8)?),
1279            0x19 => visitor.visit_i16x8_extract_lane_u(self.read_lane_index(8)?),
1280            0x1a => visitor.visit_i16x8_replace_lane(self.read_lane_index(8)?),
1281            0x1b => visitor.visit_i32x4_extract_lane(self.read_lane_index(4)?),
1282
1283            0x1c => visitor.visit_i32x4_replace_lane(self.read_lane_index(4)?),
1284            0x1d => visitor.visit_i64x2_extract_lane(self.read_lane_index(2)?),
1285            0x1e => visitor.visit_i64x2_replace_lane(self.read_lane_index(2)?),
1286            0x1f => visitor.visit_f32x4_extract_lane(self.read_lane_index(4)?),
1287            0x20 => visitor.visit_f32x4_replace_lane(self.read_lane_index(4)?),
1288            0x21 => visitor.visit_f64x2_extract_lane(self.read_lane_index(2)?),
1289            0x22 => visitor.visit_f64x2_replace_lane(self.read_lane_index(2)?),
1290
1291            0x23 => visitor.visit_i8x16_eq(),
1292            0x24 => visitor.visit_i8x16_ne(),
1293            0x25 => visitor.visit_i8x16_lt_s(),
1294            0x26 => visitor.visit_i8x16_lt_u(),
1295            0x27 => visitor.visit_i8x16_gt_s(),
1296            0x28 => visitor.visit_i8x16_gt_u(),
1297            0x29 => visitor.visit_i8x16_le_s(),
1298            0x2a => visitor.visit_i8x16_le_u(),
1299            0x2b => visitor.visit_i8x16_ge_s(),
1300            0x2c => visitor.visit_i8x16_ge_u(),
1301            0x2d => visitor.visit_i16x8_eq(),
1302            0x2e => visitor.visit_i16x8_ne(),
1303            0x2f => visitor.visit_i16x8_lt_s(),
1304            0x30 => visitor.visit_i16x8_lt_u(),
1305            0x31 => visitor.visit_i16x8_gt_s(),
1306            0x32 => visitor.visit_i16x8_gt_u(),
1307            0x33 => visitor.visit_i16x8_le_s(),
1308            0x34 => visitor.visit_i16x8_le_u(),
1309            0x35 => visitor.visit_i16x8_ge_s(),
1310            0x36 => visitor.visit_i16x8_ge_u(),
1311            0x37 => visitor.visit_i32x4_eq(),
1312            0x38 => visitor.visit_i32x4_ne(),
1313            0x39 => visitor.visit_i32x4_lt_s(),
1314            0x3a => visitor.visit_i32x4_lt_u(),
1315            0x3b => visitor.visit_i32x4_gt_s(),
1316            0x3c => visitor.visit_i32x4_gt_u(),
1317            0x3d => visitor.visit_i32x4_le_s(),
1318            0x3e => visitor.visit_i32x4_le_u(),
1319            0x3f => visitor.visit_i32x4_ge_s(),
1320            0x40 => visitor.visit_i32x4_ge_u(),
1321            0x41 => visitor.visit_f32x4_eq(),
1322            0x42 => visitor.visit_f32x4_ne(),
1323            0x43 => visitor.visit_f32x4_lt(),
1324            0x44 => visitor.visit_f32x4_gt(),
1325            0x45 => visitor.visit_f32x4_le(),
1326            0x46 => visitor.visit_f32x4_ge(),
1327            0x47 => visitor.visit_f64x2_eq(),
1328            0x48 => visitor.visit_f64x2_ne(),
1329            0x49 => visitor.visit_f64x2_lt(),
1330            0x4a => visitor.visit_f64x2_gt(),
1331            0x4b => visitor.visit_f64x2_le(),
1332            0x4c => visitor.visit_f64x2_ge(),
1333            0x4d => visitor.visit_v128_not(),
1334            0x4e => visitor.visit_v128_and(),
1335            0x4f => visitor.visit_v128_andnot(),
1336            0x50 => visitor.visit_v128_or(),
1337            0x51 => visitor.visit_v128_xor(),
1338            0x52 => visitor.visit_v128_bitselect(),
1339            0x53 => visitor.visit_v128_any_true(),
1340
1341            0x54 => {
1342                let memarg = self.read_memarg(0)?;
1343                let lane = self.read_lane_index(16)?;
1344                visitor.visit_v128_load8_lane(memarg, lane)
1345            }
1346            0x55 => {
1347                let memarg = self.read_memarg(1)?;
1348                let lane = self.read_lane_index(8)?;
1349                visitor.visit_v128_load16_lane(memarg, lane)
1350            }
1351            0x56 => {
1352                let memarg = self.read_memarg(2)?;
1353                let lane = self.read_lane_index(4)?;
1354                visitor.visit_v128_load32_lane(memarg, lane)
1355            }
1356            0x57 => {
1357                let memarg = self.read_memarg(3)?;
1358                let lane = self.read_lane_index(2)?;
1359                visitor.visit_v128_load64_lane(memarg, lane)
1360            }
1361            0x58 => {
1362                let memarg = self.read_memarg(0)?;
1363                let lane = self.read_lane_index(16)?;
1364                visitor.visit_v128_store8_lane(memarg, lane)
1365            }
1366            0x59 => {
1367                let memarg = self.read_memarg(1)?;
1368                let lane = self.read_lane_index(8)?;
1369                visitor.visit_v128_store16_lane(memarg, lane)
1370            }
1371            0x5a => {
1372                let memarg = self.read_memarg(2)?;
1373                let lane = self.read_lane_index(4)?;
1374                visitor.visit_v128_store32_lane(memarg, lane)
1375            }
1376            0x5b => {
1377                let memarg = self.read_memarg(3)?;
1378                let lane = self.read_lane_index(2)?;
1379                visitor.visit_v128_store64_lane(memarg, lane)
1380            }
1381
1382            0x5c => visitor.visit_v128_load32_zero(self.read_memarg(2)?),
1383            0x5d => visitor.visit_v128_load64_zero(self.read_memarg(3)?),
1384            0x5e => visitor.visit_f32x4_demote_f64x2_zero(),
1385            0x5f => visitor.visit_f64x2_promote_low_f32x4(),
1386            0x60 => visitor.visit_i8x16_abs(),
1387            0x61 => visitor.visit_i8x16_neg(),
1388            0x62 => visitor.visit_i8x16_popcnt(),
1389            0x63 => visitor.visit_i8x16_all_true(),
1390            0x64 => visitor.visit_i8x16_bitmask(),
1391            0x65 => visitor.visit_i8x16_narrow_i16x8_s(),
1392            0x66 => visitor.visit_i8x16_narrow_i16x8_u(),
1393            0x67 => visitor.visit_f32x4_ceil(),
1394            0x68 => visitor.visit_f32x4_floor(),
1395            0x69 => visitor.visit_f32x4_trunc(),
1396            0x6a => visitor.visit_f32x4_nearest(),
1397            0x6b => visitor.visit_i8x16_shl(),
1398            0x6c => visitor.visit_i8x16_shr_s(),
1399            0x6d => visitor.visit_i8x16_shr_u(),
1400            0x6e => visitor.visit_i8x16_add(),
1401            0x6f => visitor.visit_i8x16_add_sat_s(),
1402            0x70 => visitor.visit_i8x16_add_sat_u(),
1403            0x71 => visitor.visit_i8x16_sub(),
1404            0x72 => visitor.visit_i8x16_sub_sat_s(),
1405            0x73 => visitor.visit_i8x16_sub_sat_u(),
1406            0x74 => visitor.visit_f64x2_ceil(),
1407            0x75 => visitor.visit_f64x2_floor(),
1408            0x76 => visitor.visit_i8x16_min_s(),
1409            0x77 => visitor.visit_i8x16_min_u(),
1410            0x78 => visitor.visit_i8x16_max_s(),
1411            0x79 => visitor.visit_i8x16_max_u(),
1412            0x7a => visitor.visit_f64x2_trunc(),
1413            0x7b => visitor.visit_i8x16_avgr_u(),
1414            0x7c => visitor.visit_i16x8_extadd_pairwise_i8x16_s(),
1415            0x7d => visitor.visit_i16x8_extadd_pairwise_i8x16_u(),
1416            0x7e => visitor.visit_i32x4_extadd_pairwise_i16x8_s(),
1417            0x7f => visitor.visit_i32x4_extadd_pairwise_i16x8_u(),
1418            0x80 => visitor.visit_i16x8_abs(),
1419            0x81 => visitor.visit_i16x8_neg(),
1420            0x82 => visitor.visit_i16x8_q15mulr_sat_s(),
1421            0x83 => visitor.visit_i16x8_all_true(),
1422            0x84 => visitor.visit_i16x8_bitmask(),
1423            0x85 => visitor.visit_i16x8_narrow_i32x4_s(),
1424            0x86 => visitor.visit_i16x8_narrow_i32x4_u(),
1425            0x87 => visitor.visit_i16x8_extend_low_i8x16_s(),
1426            0x88 => visitor.visit_i16x8_extend_high_i8x16_s(),
1427            0x89 => visitor.visit_i16x8_extend_low_i8x16_u(),
1428            0x8a => visitor.visit_i16x8_extend_high_i8x16_u(),
1429            0x8b => visitor.visit_i16x8_shl(),
1430            0x8c => visitor.visit_i16x8_shr_s(),
1431            0x8d => visitor.visit_i16x8_shr_u(),
1432            0x8e => visitor.visit_i16x8_add(),
1433            0x8f => visitor.visit_i16x8_add_sat_s(),
1434            0x90 => visitor.visit_i16x8_add_sat_u(),
1435            0x91 => visitor.visit_i16x8_sub(),
1436            0x92 => visitor.visit_i16x8_sub_sat_s(),
1437            0x93 => visitor.visit_i16x8_sub_sat_u(),
1438            0x94 => visitor.visit_f64x2_nearest(),
1439            0x95 => visitor.visit_i16x8_mul(),
1440            0x96 => visitor.visit_i16x8_min_s(),
1441            0x97 => visitor.visit_i16x8_min_u(),
1442            0x98 => visitor.visit_i16x8_max_s(),
1443            0x99 => visitor.visit_i16x8_max_u(),
1444            0x9b => visitor.visit_i16x8_avgr_u(),
1445            0x9c => visitor.visit_i16x8_extmul_low_i8x16_s(),
1446            0x9d => visitor.visit_i16x8_extmul_high_i8x16_s(),
1447            0x9e => visitor.visit_i16x8_extmul_low_i8x16_u(),
1448            0x9f => visitor.visit_i16x8_extmul_high_i8x16_u(),
1449            0xa0 => visitor.visit_i32x4_abs(),
1450            0xa1 => visitor.visit_i32x4_neg(),
1451            0xa3 => visitor.visit_i32x4_all_true(),
1452            0xa4 => visitor.visit_i32x4_bitmask(),
1453            0xa7 => visitor.visit_i32x4_extend_low_i16x8_s(),
1454            0xa8 => visitor.visit_i32x4_extend_high_i16x8_s(),
1455            0xa9 => visitor.visit_i32x4_extend_low_i16x8_u(),
1456            0xaa => visitor.visit_i32x4_extend_high_i16x8_u(),
1457            0xab => visitor.visit_i32x4_shl(),
1458            0xac => visitor.visit_i32x4_shr_s(),
1459            0xad => visitor.visit_i32x4_shr_u(),
1460            0xae => visitor.visit_i32x4_add(),
1461            0xb1 => visitor.visit_i32x4_sub(),
1462            0xb5 => visitor.visit_i32x4_mul(),
1463            0xb6 => visitor.visit_i32x4_min_s(),
1464            0xb7 => visitor.visit_i32x4_min_u(),
1465            0xb8 => visitor.visit_i32x4_max_s(),
1466            0xb9 => visitor.visit_i32x4_max_u(),
1467            0xba => visitor.visit_i32x4_dot_i16x8_s(),
1468            0xbc => visitor.visit_i32x4_extmul_low_i16x8_s(),
1469            0xbd => visitor.visit_i32x4_extmul_high_i16x8_s(),
1470            0xbe => visitor.visit_i32x4_extmul_low_i16x8_u(),
1471            0xbf => visitor.visit_i32x4_extmul_high_i16x8_u(),
1472            0xc0 => visitor.visit_i64x2_abs(),
1473            0xc1 => visitor.visit_i64x2_neg(),
1474            0xc3 => visitor.visit_i64x2_all_true(),
1475            0xc4 => visitor.visit_i64x2_bitmask(),
1476            0xc7 => visitor.visit_i64x2_extend_low_i32x4_s(),
1477            0xc8 => visitor.visit_i64x2_extend_high_i32x4_s(),
1478            0xc9 => visitor.visit_i64x2_extend_low_i32x4_u(),
1479            0xca => visitor.visit_i64x2_extend_high_i32x4_u(),
1480            0xcb => visitor.visit_i64x2_shl(),
1481            0xcc => visitor.visit_i64x2_shr_s(),
1482            0xcd => visitor.visit_i64x2_shr_u(),
1483            0xce => visitor.visit_i64x2_add(),
1484            0xd1 => visitor.visit_i64x2_sub(),
1485            0xd5 => visitor.visit_i64x2_mul(),
1486            0xd6 => visitor.visit_i64x2_eq(),
1487            0xd7 => visitor.visit_i64x2_ne(),
1488            0xd8 => visitor.visit_i64x2_lt_s(),
1489            0xd9 => visitor.visit_i64x2_gt_s(),
1490            0xda => visitor.visit_i64x2_le_s(),
1491            0xdb => visitor.visit_i64x2_ge_s(),
1492            0xdc => visitor.visit_i64x2_extmul_low_i32x4_s(),
1493            0xdd => visitor.visit_i64x2_extmul_high_i32x4_s(),
1494            0xde => visitor.visit_i64x2_extmul_low_i32x4_u(),
1495            0xdf => visitor.visit_i64x2_extmul_high_i32x4_u(),
1496            0xe0 => visitor.visit_f32x4_abs(),
1497            0xe1 => visitor.visit_f32x4_neg(),
1498            0xe3 => visitor.visit_f32x4_sqrt(),
1499            0xe4 => visitor.visit_f32x4_add(),
1500            0xe5 => visitor.visit_f32x4_sub(),
1501            0xe6 => visitor.visit_f32x4_mul(),
1502            0xe7 => visitor.visit_f32x4_div(),
1503            0xe8 => visitor.visit_f32x4_min(),
1504            0xe9 => visitor.visit_f32x4_max(),
1505            0xea => visitor.visit_f32x4_pmin(),
1506            0xeb => visitor.visit_f32x4_pmax(),
1507            0xec => visitor.visit_f64x2_abs(),
1508            0xed => visitor.visit_f64x2_neg(),
1509            0xef => visitor.visit_f64x2_sqrt(),
1510            0xf0 => visitor.visit_f64x2_add(),
1511            0xf1 => visitor.visit_f64x2_sub(),
1512            0xf2 => visitor.visit_f64x2_mul(),
1513            0xf3 => visitor.visit_f64x2_div(),
1514            0xf4 => visitor.visit_f64x2_min(),
1515            0xf5 => visitor.visit_f64x2_max(),
1516            0xf6 => visitor.visit_f64x2_pmin(),
1517            0xf7 => visitor.visit_f64x2_pmax(),
1518            0xf8 => visitor.visit_i32x4_trunc_sat_f32x4_s(),
1519            0xf9 => visitor.visit_i32x4_trunc_sat_f32x4_u(),
1520            0xfa => visitor.visit_f32x4_convert_i32x4_s(),
1521            0xfb => visitor.visit_f32x4_convert_i32x4_u(),
1522            0xfc => visitor.visit_i32x4_trunc_sat_f64x2_s_zero(),
1523            0xfd => visitor.visit_i32x4_trunc_sat_f64x2_u_zero(),
1524            0xfe => visitor.visit_f64x2_convert_low_i32x4_s(),
1525            0xff => visitor.visit_f64x2_convert_low_i32x4_u(),
1526            0x100 => visitor.visit_i8x16_relaxed_swizzle(),
1527            0x101 => visitor.visit_i32x4_relaxed_trunc_f32x4_s(),
1528            0x102 => visitor.visit_i32x4_relaxed_trunc_f32x4_u(),
1529            0x103 => visitor.visit_i32x4_relaxed_trunc_f64x2_s_zero(),
1530            0x104 => visitor.visit_i32x4_relaxed_trunc_f64x2_u_zero(),
1531            0x105 => visitor.visit_f32x4_relaxed_madd(),
1532            0x106 => visitor.visit_f32x4_relaxed_nmadd(),
1533            0x107 => visitor.visit_f64x2_relaxed_madd(),
1534            0x108 => visitor.visit_f64x2_relaxed_nmadd(),
1535            0x109 => visitor.visit_i8x16_relaxed_laneselect(),
1536            0x10a => visitor.visit_i16x8_relaxed_laneselect(),
1537            0x10b => visitor.visit_i32x4_relaxed_laneselect(),
1538            0x10c => visitor.visit_i64x2_relaxed_laneselect(),
1539            0x10d => visitor.visit_f32x4_relaxed_min(),
1540            0x10e => visitor.visit_f32x4_relaxed_max(),
1541            0x10f => visitor.visit_f64x2_relaxed_min(),
1542            0x110 => visitor.visit_f64x2_relaxed_max(),
1543            0x111 => visitor.visit_i16x8_relaxed_q15mulr_s(),
1544            0x112 => visitor.visit_i16x8_relaxed_dot_i8x16_i7x16_s(),
1545            0x113 => visitor.visit_i32x4_relaxed_dot_i8x16_i7x16_add_s(),
1546
1547            _ => bail!(pos, "unknown 0xfd subopcode: 0x{code:x}"),
1548        })
1549    }
1550
1551    fn visit_0xfe_operator<T>(
1552        &mut self,
1553        pos: usize,
1554        visitor: &mut T,
1555    ) -> Result<<T as VisitOperator<'a>>::Output>
1556    where
1557        T: VisitOperator<'a>,
1558    {
1559        let code = self.read_var_u32()?;
1560        Ok(match code {
1561            0x00 => visitor.visit_memory_atomic_notify(self.read_memarg(2)?),
1562            0x01 => visitor.visit_memory_atomic_wait32(self.read_memarg(2)?),
1563            0x02 => visitor.visit_memory_atomic_wait64(self.read_memarg(3)?),
1564            0x03 => {
1565                if self.read_u8()? != 0 {
1566                    bail!(pos, "nonzero byte after `atomic.fence`");
1567                }
1568                visitor.visit_atomic_fence()
1569            }
1570            0x10 => visitor.visit_i32_atomic_load(self.read_memarg(2)?),
1571            0x11 => visitor.visit_i64_atomic_load(self.read_memarg(3)?),
1572            0x12 => visitor.visit_i32_atomic_load8_u(self.read_memarg(0)?),
1573            0x13 => visitor.visit_i32_atomic_load16_u(self.read_memarg(1)?),
1574            0x14 => visitor.visit_i64_atomic_load8_u(self.read_memarg(0)?),
1575            0x15 => visitor.visit_i64_atomic_load16_u(self.read_memarg(1)?),
1576            0x16 => visitor.visit_i64_atomic_load32_u(self.read_memarg(2)?),
1577            0x17 => visitor.visit_i32_atomic_store(self.read_memarg(2)?),
1578            0x18 => visitor.visit_i64_atomic_store(self.read_memarg(3)?),
1579            0x19 => visitor.visit_i32_atomic_store8(self.read_memarg(0)?),
1580            0x1a => visitor.visit_i32_atomic_store16(self.read_memarg(1)?),
1581            0x1b => visitor.visit_i64_atomic_store8(self.read_memarg(0)?),
1582            0x1c => visitor.visit_i64_atomic_store16(self.read_memarg(1)?),
1583            0x1d => visitor.visit_i64_atomic_store32(self.read_memarg(2)?),
1584            0x1e => visitor.visit_i32_atomic_rmw_add(self.read_memarg(2)?),
1585            0x1f => visitor.visit_i64_atomic_rmw_add(self.read_memarg(3)?),
1586            0x20 => visitor.visit_i32_atomic_rmw8_add_u(self.read_memarg(0)?),
1587            0x21 => visitor.visit_i32_atomic_rmw16_add_u(self.read_memarg(1)?),
1588            0x22 => visitor.visit_i64_atomic_rmw8_add_u(self.read_memarg(0)?),
1589            0x23 => visitor.visit_i64_atomic_rmw16_add_u(self.read_memarg(1)?),
1590            0x24 => visitor.visit_i64_atomic_rmw32_add_u(self.read_memarg(2)?),
1591            0x25 => visitor.visit_i32_atomic_rmw_sub(self.read_memarg(2)?),
1592            0x26 => visitor.visit_i64_atomic_rmw_sub(self.read_memarg(3)?),
1593            0x27 => visitor.visit_i32_atomic_rmw8_sub_u(self.read_memarg(0)?),
1594            0x28 => visitor.visit_i32_atomic_rmw16_sub_u(self.read_memarg(1)?),
1595            0x29 => visitor.visit_i64_atomic_rmw8_sub_u(self.read_memarg(0)?),
1596            0x2a => visitor.visit_i64_atomic_rmw16_sub_u(self.read_memarg(1)?),
1597            0x2b => visitor.visit_i64_atomic_rmw32_sub_u(self.read_memarg(2)?),
1598            0x2c => visitor.visit_i32_atomic_rmw_and(self.read_memarg(2)?),
1599            0x2d => visitor.visit_i64_atomic_rmw_and(self.read_memarg(3)?),
1600            0x2e => visitor.visit_i32_atomic_rmw8_and_u(self.read_memarg(0)?),
1601            0x2f => visitor.visit_i32_atomic_rmw16_and_u(self.read_memarg(1)?),
1602            0x30 => visitor.visit_i64_atomic_rmw8_and_u(self.read_memarg(0)?),
1603            0x31 => visitor.visit_i64_atomic_rmw16_and_u(self.read_memarg(1)?),
1604            0x32 => visitor.visit_i64_atomic_rmw32_and_u(self.read_memarg(2)?),
1605            0x33 => visitor.visit_i32_atomic_rmw_or(self.read_memarg(2)?),
1606            0x34 => visitor.visit_i64_atomic_rmw_or(self.read_memarg(3)?),
1607            0x35 => visitor.visit_i32_atomic_rmw8_or_u(self.read_memarg(0)?),
1608            0x36 => visitor.visit_i32_atomic_rmw16_or_u(self.read_memarg(1)?),
1609            0x37 => visitor.visit_i64_atomic_rmw8_or_u(self.read_memarg(0)?),
1610            0x38 => visitor.visit_i64_atomic_rmw16_or_u(self.read_memarg(1)?),
1611            0x39 => visitor.visit_i64_atomic_rmw32_or_u(self.read_memarg(2)?),
1612            0x3a => visitor.visit_i32_atomic_rmw_xor(self.read_memarg(2)?),
1613            0x3b => visitor.visit_i64_atomic_rmw_xor(self.read_memarg(3)?),
1614            0x3c => visitor.visit_i32_atomic_rmw8_xor_u(self.read_memarg(0)?),
1615            0x3d => visitor.visit_i32_atomic_rmw16_xor_u(self.read_memarg(1)?),
1616            0x3e => visitor.visit_i64_atomic_rmw8_xor_u(self.read_memarg(0)?),
1617            0x3f => visitor.visit_i64_atomic_rmw16_xor_u(self.read_memarg(1)?),
1618            0x40 => visitor.visit_i64_atomic_rmw32_xor_u(self.read_memarg(2)?),
1619            0x41 => visitor.visit_i32_atomic_rmw_xchg(self.read_memarg(2)?),
1620            0x42 => visitor.visit_i64_atomic_rmw_xchg(self.read_memarg(3)?),
1621            0x43 => visitor.visit_i32_atomic_rmw8_xchg_u(self.read_memarg(0)?),
1622            0x44 => visitor.visit_i32_atomic_rmw16_xchg_u(self.read_memarg(1)?),
1623            0x45 => visitor.visit_i64_atomic_rmw8_xchg_u(self.read_memarg(0)?),
1624            0x46 => visitor.visit_i64_atomic_rmw16_xchg_u(self.read_memarg(1)?),
1625            0x47 => visitor.visit_i64_atomic_rmw32_xchg_u(self.read_memarg(2)?),
1626            0x48 => visitor.visit_i32_atomic_rmw_cmpxchg(self.read_memarg(2)?),
1627            0x49 => visitor.visit_i64_atomic_rmw_cmpxchg(self.read_memarg(3)?),
1628            0x4a => visitor.visit_i32_atomic_rmw8_cmpxchg_u(self.read_memarg(0)?),
1629            0x4b => visitor.visit_i32_atomic_rmw16_cmpxchg_u(self.read_memarg(1)?),
1630            0x4c => visitor.visit_i64_atomic_rmw8_cmpxchg_u(self.read_memarg(0)?),
1631            0x4d => visitor.visit_i64_atomic_rmw16_cmpxchg_u(self.read_memarg(1)?),
1632            0x4e => visitor.visit_i64_atomic_rmw32_cmpxchg_u(self.read_memarg(2)?),
1633
1634            _ => bail!(pos, "unknown 0xfe subopcode: 0x{code:x}"),
1635        })
1636    }
1637
1638    /// Reads the next available `Operator`.
1639    ///
1640    /// # Errors
1641    ///
1642    /// If `BinaryReader` has less bytes remaining than required to parse
1643    /// the `Operator`.
1644    pub fn read_operator(&mut self) -> Result<Operator<'a>> {
1645        self.visit_operator(&mut OperatorFactory::new())
1646    }
1647
1648    fn read_lane_index(&mut self, max: u8) -> Result<u8> {
1649        let index = self.read_u8()?;
1650        if index >= max {
1651            return Err(BinaryReaderError::new(
1652                "invalid lane index",
1653                self.original_position() - 1,
1654            ));
1655        }
1656        Ok(index)
1657    }
1658
1659    fn read_v128(&mut self) -> Result<V128> {
1660        let mut bytes = [0; 16];
1661        bytes.clone_from_slice(self.read_bytes(16)?);
1662        Ok(V128(bytes))
1663    }
1664
1665    pub(crate) fn read_header_version(&mut self) -> Result<u32> {
1666        let magic_number = self.read_bytes(4)?;
1667        if magic_number != WASM_MAGIC_NUMBER {
1668            return Err(BinaryReaderError::new(
1669                format!("magic header not detected: bad magic number - expected={WASM_MAGIC_NUMBER:#x?} actual={magic_number:#x?}"),
1670                self.original_position() - 4,
1671            ));
1672        }
1673        self.read_u32()
1674    }
1675
1676    pub(crate) fn skip_const_expr(&mut self) -> Result<()> {
1677        // TODO add skip_operator() method and/or validate ConstExpr operators.
1678        loop {
1679            if let Operator::End = self.read_operator()? {
1680                return Ok(());
1681            }
1682        }
1683    }
1684}
1685
1686impl<'a> BrTable<'a> {
1687    /// Returns the number of `br_table` entries, not including the default
1688    /// label
1689    pub fn len(&self) -> u32 {
1690        self.cnt
1691    }
1692
1693    /// Returns whether `BrTable` doesn't have any labels apart from the default one.
1694    pub fn is_empty(&self) -> bool {
1695        self.len() == 0
1696    }
1697
1698    /// Returns the default target of this `br_table` instruction.
1699    pub fn default(&self) -> u32 {
1700        self.default
1701    }
1702
1703    /// Returns the list of targets that this `br_table` instruction will be
1704    /// jumping to.
1705    ///
1706    /// This method will return an iterator which parses each target of this
1707    /// `br_table` except the default target. The returned iterator will
1708    /// yield `self.len()` elements.
1709    ///
1710    /// # Examples
1711    ///
1712    /// ```rust
1713    /// let buf = [0x0e, 0x02, 0x01, 0x02, 0x00];
1714    /// let mut reader = tinywasm_wasmparser::BinaryReader::new(&buf);
1715    /// let op = reader.read_operator().unwrap();
1716    /// if let tinywasm_wasmparser::Operator::BrTable { targets } = op {
1717    ///     let targets = targets.targets().collect::<Result<Vec<_>, _>>().unwrap();
1718    ///     assert_eq!(targets, [1, 2]);
1719    /// }
1720    /// ```
1721    pub fn targets(&self) -> BrTableTargets {
1722        BrTableTargets {
1723            reader: self.reader.clone(),
1724            remaining: self.cnt,
1725        }
1726    }
1727}
1728
1729/// An iterator over the targets of a [`BrTable`].
1730///
1731/// # Note
1732///
1733/// This iterator parses each target of the underlying `br_table`
1734/// except for the default target.
1735/// The iterator will yield exactly as many targets as the `br_table` has.
1736pub struct BrTableTargets<'a> {
1737    reader: crate::BinaryReader<'a>,
1738    remaining: u32,
1739}
1740
1741impl<'a> Iterator for BrTableTargets<'a> {
1742    type Item = Result<u32>;
1743
1744    fn size_hint(&self) -> (usize, Option<usize>) {
1745        let remaining = usize::try_from(self.remaining).unwrap_or_else(|error| {
1746            panic!("could not convert remaining `u32` into `usize`: {}", error)
1747        });
1748        (remaining, Some(remaining))
1749    }
1750
1751    fn next(&mut self) -> Option<Self::Item> {
1752        if self.remaining == 0 {
1753            if !self.reader.eof() {
1754                return Some(Err(BinaryReaderError::new(
1755                    "trailing data in br_table",
1756                    self.reader.original_position(),
1757                )));
1758            }
1759            return None;
1760        }
1761        self.remaining -= 1;
1762        Some(self.reader.read_var_u32())
1763    }
1764}
1765
1766impl fmt::Debug for BrTable<'_> {
1767    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1768        let mut f = f.debug_struct("BrTable");
1769        f.field("count", &self.cnt);
1770        f.field("default", &self.default);
1771        match self.targets().collect::<Result<Vec<_>>>() {
1772            Ok(targets) => {
1773                f.field("targets", &targets);
1774            }
1775            Err(_) => {
1776                f.field("reader", &self.reader);
1777            }
1778        }
1779        f.finish()
1780    }
1781}
1782
1783/// A factory to construct [`Operator`] instances via the [`VisitOperator`] trait.
1784struct OperatorFactory<'a> {
1785    marker: core::marker::PhantomData<fn() -> &'a ()>,
1786}
1787
1788impl<'a> OperatorFactory<'a> {
1789    /// Creates a new [`OperatorFactory`].
1790    fn new() -> Self {
1791        Self {
1792            marker: core::marker::PhantomData,
1793        }
1794    }
1795}
1796
1797macro_rules! define_visit_operator {
1798    ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
1799        $(
1800            fn $visit(&mut self $($(,$arg: $argty)*)?) -> Operator<'a> {
1801                Operator::$op $({ $($arg),* })?
1802            }
1803        )*
1804    }
1805}
1806
1807impl<'a> VisitOperator<'a> for OperatorFactory<'a> {
1808    type Output = Operator<'a>;
1809
1810    for_each_operator!(define_visit_operator);
1811}
1812
1813/// Iterator returned from [`BinaryReader::read_iter`].
1814pub struct BinaryReaderIter<'a, 'me, T: FromReader<'a>> {
1815    remaining: usize,
1816    pub(crate) reader: &'me mut BinaryReader<'a>,
1817    _marker: marker::PhantomData<T>,
1818}
1819
1820impl<'a, T> Iterator for BinaryReaderIter<'a, '_, T>
1821where
1822    T: FromReader<'a>,
1823{
1824    type Item = Result<T>;
1825
1826    fn next(&mut self) -> Option<Result<T>> {
1827        if self.remaining == 0 {
1828            None
1829        } else {
1830            let ret = self.reader.read::<T>();
1831            if ret.is_err() {
1832                self.remaining = 0;
1833            } else {
1834                self.remaining -= 1;
1835            }
1836            Some(ret)
1837        }
1838    }
1839
1840    fn size_hint(&self) -> (usize, Option<usize>) {
1841        (self.remaining, Some(self.remaining))
1842    }
1843}
1844
1845impl<'a, T> Drop for BinaryReaderIter<'a, '_, T>
1846where
1847    T: FromReader<'a>,
1848{
1849    fn drop(&mut self) {
1850        while self.next().is_some() {
1851            // ...
1852        }
1853    }
1854}