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