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