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