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