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