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