///|
pub suberror BinaryDecodeError {
IndexOutOfBounds
InvalidNumTypeByte
InvalidAbstractHeapType
InvalidValType
InvalidCompType
UnexpectedEofDecodingMut
InvalidMutByte
InvalidStorageType
InvalidPackedType
InvalidUnsignedLebBitWidth
UnexpectedEofInUnsignedLeb
UnsignedLebTooManyBytes
UnsignedLebOutOfRangeForBitWidth
UnsignedLebTerminalHasNonZeroUnusedBits
UnreachableDecodeState
InvalidSignedLebBitWidth
UnexpectedEofInSignedLeb
SignedLebTooManyBytes
SignedLebOutOfRangeForBitWidth
SignedLebPositiveTerminalHasNonZeroUnusedBits
SignedLebTerminalHasWrongSignExtensionBits
InvalidS33Range
InvalidBoolByte
InvalidLaneIndex
NegativeNameLength
InvalidUtf8Name
InvalidSectionHeader
SectionPayloadLengthOutOfRange
InvalidSectionPayloadTrailingBytes
DuplicateNameSection
DuplicateCompilerFactsSection
InvalidCompilerFactsEnumTag
InvalidCompilerFactsOptionTag
TruncatedCompilerFactsPayload
CompilerFactsTrailingBytes
UnsupportedCompilerFactsVersion
InvalidNameSubsectionId
InvalidNameSubsectionOrder
InvalidNameMapOrder
InvalidMagicHeader
InvalidModule
InvalidElemHeader
InvalidDataHeader
CustomSectionPayloadLengthOutOfRange
InvalidLimits
InvalidTagType
InvalidExternTypeHeader
InvalidBlockType
InvalidExternIndex
InvalidOffset
InvalidCatch
InvalidCastOp
InvalidMemArg
InvalidStringRefSection
InvalidStringLiteralIndex
InvalidInstruction
InvalidAtomicFenceImmediate
InvalidAtomicInstruction
InstructionNestingLimitExceeded
} derive(Eq, Debug)
///|
pub impl Show for BinaryDecodeError with fn output(self, logger) {
match self {
IndexOutOfBounds => logger.write_string("IndexOutOfBounds")
InvalidNumTypeByte => logger.write_string("InvalidNumTypeByte")
InvalidAbstractHeapType => logger.write_string("InvalidAbstractHeapType")
InvalidValType => logger.write_string("InvalidValType")
InvalidCompType => logger.write_string("InvalidCompType")
UnexpectedEofDecodingMut => logger.write_string("UnexpectedEofDecodingMut")
InvalidMutByte => logger.write_string("InvalidMutByte")
InvalidStorageType => logger.write_string("InvalidStorageType")
InvalidPackedType => logger.write_string("InvalidPackedType")
InvalidUnsignedLebBitWidth =>
logger.write_string("InvalidUnsignedLebBitWidth")
UnexpectedEofInUnsignedLeb =>
logger.write_string("UnexpectedEofInUnsignedLeb")
UnsignedLebTooManyBytes => logger.write_string("UnsignedLebTooManyBytes")
UnsignedLebOutOfRangeForBitWidth =>
logger.write_string("UnsignedLebOutOfRangeForBitWidth")
UnsignedLebTerminalHasNonZeroUnusedBits =>
logger.write_string("UnsignedLebTerminalHasNonZeroUnusedBits")
UnreachableDecodeState => logger.write_string("UnreachableDecodeState")
InvalidSignedLebBitWidth => logger.write_string("InvalidSignedLebBitWidth")
UnexpectedEofInSignedLeb => logger.write_string("UnexpectedEofInSignedLeb")
SignedLebTooManyBytes => logger.write_string("SignedLebTooManyBytes")
SignedLebOutOfRangeForBitWidth =>
logger.write_string("SignedLebOutOfRangeForBitWidth")
SignedLebPositiveTerminalHasNonZeroUnusedBits =>
logger.write_string("SignedLebPositiveTerminalHasNonZeroUnusedBits")
SignedLebTerminalHasWrongSignExtensionBits =>
logger.write_string("SignedLebTerminalHasWrongSignExtensionBits")
InvalidS33Range => logger.write_string("InvalidS33Range")
InvalidBoolByte => logger.write_string("InvalidBoolByte")
InvalidLaneIndex => logger.write_string("InvalidLaneIndex")
NegativeNameLength => logger.write_string("NegativeNameLength")
InvalidUtf8Name => logger.write_string("InvalidUtf8Name")
InvalidSectionHeader => logger.write_string("InvalidSectionHeader")
SectionPayloadLengthOutOfRange =>
logger.write_string("SectionPayloadLengthOutOfRange")
InvalidSectionPayloadTrailingBytes =>
logger.write_string("InvalidSectionPayloadTrailingBytes")
DuplicateNameSection => logger.write_string("DuplicateNameSection")
DuplicateCompilerFactsSection =>
logger.write_string("DuplicateCompilerFactsSection")
InvalidCompilerFactsEnumTag =>
logger.write_string("InvalidCompilerFactsEnumTag")
InvalidCompilerFactsOptionTag =>
logger.write_string("InvalidCompilerFactsOptionTag")
TruncatedCompilerFactsPayload =>
logger.write_string("TruncatedCompilerFactsPayload")
CompilerFactsTrailingBytes =>
logger.write_string("CompilerFactsTrailingBytes")
UnsupportedCompilerFactsVersion =>
logger.write_string("UnsupportedCompilerFactsVersion")
InvalidNameSubsectionId => logger.write_string("InvalidNameSubsectionId")
InvalidNameSubsectionOrder =>
logger.write_string("InvalidNameSubsectionOrder")
InvalidNameMapOrder => logger.write_string("InvalidNameMapOrder")
InvalidMagicHeader => logger.write_string("InvalidMagicHeader")
InvalidModule => logger.write_string("InvalidModule")
InvalidElemHeader => logger.write_string("InvalidElemHeader")
InvalidDataHeader => logger.write_string("InvalidDataHeader")
CustomSectionPayloadLengthOutOfRange =>
logger.write_string("CustomSectionPayloadLengthOutOfRange")
InvalidLimits => logger.write_string("InvalidLimits")
InvalidTagType => logger.write_string("InvalidTagType")
InvalidExternTypeHeader => logger.write_string("InvalidExternTypeHeader")
InvalidBlockType => logger.write_string("InvalidBlockType")
InvalidExternIndex => logger.write_string("InvalidExternIndex")
InvalidOffset => logger.write_string("InvalidOffset")
InvalidCatch => logger.write_string("InvalidCatch")
InvalidCastOp => logger.write_string("InvalidCastOp")
InvalidMemArg => logger.write_string("InvalidMemArg")
InvalidStringRefSection => logger.write_string("InvalidStringRefSection")
InvalidStringLiteralIndex =>
logger.write_string("InvalidStringLiteralIndex")
InvalidInstruction => logger.write_string("InvalidInstruction")
InvalidAtomicFenceImmediate =>
logger.write_string("InvalidAtomicFenceImmediate")
InvalidAtomicInstruction => logger.write_string("InvalidAtomicInstruction")
InstructionNestingLimitExceeded =>
logger.write_string("InstructionNestingLimitExceeded")
}
}
///|
pub struct ModuleDecodeErrorDetail {
err : BinaryDecodeError
section_id : Int?
section_offset : Int?
section_len : Int?
trailing_offset : Int?
} derive(Eq, Debug)
///|
pub trait Decode {
fn decode(Bytes, Int) -> Result[(Self, Int), BinaryDecodeError]
}
///|
let binary_decode_stringrefs_context : Ref[Array[Bytes]?] = Ref::new(None)
///|
fn[T] with_binary_decode_stringrefs_context(
stringrefs : Array[Bytes]?,
f : () -> Result[T, ModuleDecodeErrorDetail],
) -> Result[T, ModuleDecodeErrorDetail] {
let saved = binary_decode_stringrefs_context.val
binary_decode_stringrefs_context.val = stringrefs
let result = f()
binary_decode_stringrefs_context.val = saved
result
}
///|
fn decode_string_const_literal(
idx : @lib.U32,
) -> Result[Bytes, BinaryDecodeError] {
match binary_decode_stringrefs_context.val {
Some(stringrefs) =>
match stringrefs.get(idx.0.reinterpret_as_int()) {
Some(bytes) => Ok(bytes)
None => Err(BinaryDecodeError::InvalidStringLiteralIndex)
}
None => Err(BinaryDecodeError::InvalidStringLiteralIndex)
}
}
///|
pub impl Decode for NumType with fn decode(buf, idx) {
match buf.get(idx) {
Some(0x7C) => Ok((NumType::f64(), idx + 1))
Some(0x7D) => Ok((NumType::f32(), idx + 1))
Some(0x7E) => Ok((NumType::i64(), idx + 1))
Some(0x7F) => Ok((NumType::i32(), idx + 1))
Some(_) => Err(BinaryDecodeError::InvalidNumTypeByte)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
pub impl Decode for HeapType with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x65) =>
match
(
Decode::decode(bytes, i + 1) :
Result[(AbsHeapType, Int), BinaryDecodeError]) {
Ok((abs, next)) => Ok((HeapType::shared_abs(abs), next))
Err(err) => Err(err)
}
_ =>
match Decode::decode(bytes, i) {
Ok((abs, i)) => Ok((HeapType::abs(abs), i))
Err(_) =>
match Decode::decode(bytes, i) {
Ok((@lib.S33(s), i)) => Ok((HeapType::new(TypeIdx::new(s)), i))
Err(err) => Err(err)
}
}
}
}
///|
pub impl Decode for AbsHeapType with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x5c) => Ok((AbsHeapType::waitqueue(), i + 1))
Some(0x5b) => Ok((AbsHeapType::no_waitqueue(), i + 1))
Some(0x67) => Ok((AbsHeapType::string_(), i + 1))
Some(0x68) => Ok((AbsHeapType::cont(), i + 1))
Some(0x69) => Ok((AbsHeapType::exn(), i + 1))
Some(0x6A) => Ok((AbsHeapType::array(), i + 1))
Some(0x6B) => Ok((AbsHeapType::struct_(), i + 1))
Some(0x6C) => Ok((AbsHeapType::i31(), i + 1))
Some(0x6D) => Ok((AbsHeapType::eq(), i + 1))
Some(0x6E) => Ok((AbsHeapType::any(), i + 1))
Some(0x6F) => Ok((AbsHeapType::extern_(), i + 1))
Some(0x70) => Ok((AbsHeapType::func(), i + 1))
Some(0x71) => Ok((AbsHeapType::none(), i + 1))
Some(0x72) => Ok((AbsHeapType::no_extern(), i + 1))
Some(0x73) => Ok((AbsHeapType::no_func(), i + 1))
Some(0x74) => Ok((AbsHeapType::no_exn(), i + 1))
Some(0x75) => Ok((AbsHeapType::no_cont(), i + 1))
Some(_) => Err(BinaryDecodeError::InvalidAbstractHeapType)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
fn decode_ref_heap_type(
bytes : Bytes,
i : Int,
) -> Result[(Bool, HeapType, Int), BinaryDecodeError] {
match bytes.get(i) {
Some(0x62) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.S33(s), next)) =>
Ok((true, HeapType::new(TypeIdx::new(s)), next))
Err(err) => Err(err)
}
_ =>
match Decode::decode(bytes, i) {
Ok((ht, next)) => Ok((false, ht, next))
Err(err) => Err(err)
}
}
}
///|
pub impl Decode for RefType with fn decode(bytes, i) {
match bytes.get(i) {
None => Err(BinaryDecodeError::IndexOutOfBounds)
Some(0x63) =>
match decode_ref_heap_type(bytes, i + 1) {
Err(err) => Err(err)
Ok((exact, ht, i)) =>
match (exact, ht) {
(false, AbsHeapTypeHeapType(abs)) => Ok((RefType::abs(abs), i))
_ => Ok((RefType::new(true, ht, exact~), i))
}
}
Some(0x64) =>
match decode_ref_heap_type(bytes, i + 1) {
Err(err) => Err(err)
Ok((exact, ht, i)) => Ok((RefType::new(false, ht, exact~), i))
}
Some(_) =>
match Decode::decode(bytes, i) {
Err(err) => Err(err)
Ok((abs, i)) => Ok((RefType::abs(abs), i))
}
}
}
///|
pub impl Decode for ValType with fn decode(bytes, i) {
match bytes.get(i) {
None => Err(BinaryDecodeError::IndexOutOfBounds)
Some(0x7B) => Ok((ValType::v128(), i + 1))
Some(_) =>
match Decode::decode(bytes, i) {
Ok((t, i)) => Ok((ValType::num_type(t), i))
_ =>
match Decode::decode(bytes, i) {
Ok((rt, i)) => Ok((ValType::ref_type(rt), i))
Err(err) =>
match (bytes.get(i), err) {
(Some(0x64), BinaryDecodeError::UnexpectedEofInSignedLeb)
| (Some(0x64), BinaryDecodeError::IndexOutOfBounds) =>
Ok((ValType::stringref(), i + 1))
_ => Err(BinaryDecodeError::InvalidValType)
}
}
}
}
}
///|
pub impl[T : Decode] Decode for @list.List[T] with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Ok((@lib.U32(len), i)) => {
let acc = []
let mut left = len
let mut pos = i
while left > 0 {
match T::decode(bytes, pos) {
Ok((u, next_pos)) => {
acc.push(u)
pos = next_pos
left = left - 1
}
Err(err) => return Err(err)
}
}
Ok((@list.List::from_array(acc), pos))
}
Err(err) => Err(err)
}
}
///|
pub impl Decode for CompType with fn decode(bytes, i) {
match bytes.get(i) {
None => Err(BinaryDecodeError::IndexOutOfBounds)
Some(0x5E) =>
match Decode::decode(bytes, i + 1) {
Ok((ft, i)) => Ok((CompType::array(ft), i))
Err(err) => Err(err)
}
Some(0x5F) =>
match Decode::decode(bytes, i + 1) {
Ok((fts, i)) => Ok((CompType::struct_(fts), i))
Err(err) => Err(err)
}
Some(0x60) =>
match Decode::decode(bytes, i + 1) {
Ok((props, i)) =>
match Decode::decode(bytes, i) {
Ok((rets, i)) => Ok((CompType::func(props, rets), i))
Err(err) => Err(err)
}
Err(err) => Err(err)
}
Some(0x5D) =>
match Decode::decode(bytes, i + 1) {
Ok((func_type, i)) => Ok((CompType::cont(func_type), i))
Err(err) => Err(err)
}
Some(_) => Err(BinaryDecodeError::InvalidCompType)
}
}
///|
pub impl Decode for Mut with fn decode(bytes, i) {
if i >= bytes.length() {
return Err(BinaryDecodeError::UnexpectedEofDecodingMut)
}
let b = bytes[i]
match b {
0x00 => Ok((Const, i + 1))
0x01 => Ok((Var, i + 1))
_ => Err(BinaryDecodeError::InvalidMutByte)
}
}
///|
pub impl Decode for StorageType with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Ok((vt, i)) => Ok((StorageType::val_type(vt), i))
Err(_) =>
match Decode::decode(bytes, i) {
Ok((pt, i)) => Ok((StorageType::pack_type(pt), i))
Err(_) => Err(BinaryDecodeError::InvalidStorageType)
}
}
}
///|
pub impl Decode for PackType with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x77) => Ok((PackType::i16(), i + 1))
Some(0x78) => Ok((PackType::i8(), i + 1))
Some(_) => Err(BinaryDecodeError::InvalidPackedType)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
pub impl Decode for AtomicOrder with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x00) => Ok((AtomicOrder::seq_cst(), i + 1))
Some(0x01) => Ok((AtomicOrder::acq_rel(), i + 1))
Some(0x02) => Ok((AtomicOrder::relaxed(), i + 1))
Some(_) => Err(BinaryDecodeError::InvalidAtomicInstruction)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
fn decode_aggregate_atomic_rmw_order(
bytes : Bytes,
i : Int,
) -> Result[(AtomicOrder, Int), BinaryDecodeError] {
match bytes.get(i) {
Some(0x00) => Ok((AtomicOrder::seq_cst(), i + 1))
Some(0x11) => Ok((AtomicOrder::acq_rel(), i + 1))
Some(0x22) => Ok((AtomicOrder::relaxed(), i + 1))
Some(_) => Err(BinaryDecodeError::InvalidAtomicInstruction)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
pub impl Decode for RecType with fn decode(buf, i) {
match buf.get(i) {
None => Err(BinaryDecodeError::IndexOutOfBounds)
Some(0x4E) =>
match Decode::decode(buf, i + 1) {
Ok((sts, i)) => Ok((RecType::group(sts), i))
Err(err) => Err(err)
}
Some(_) =>
match Decode::decode(buf, i) {
Ok((st, i)) => Ok((RecType::new(st), i))
Err(err) => Err(err)
}
}
}
///|
fn decode_descriptor_clauses(
buf : Bytes,
i : Int,
) -> Result[(TypeMetadata, Int), BinaryDecodeError] {
let mut cursor = i
let mut describes : TypeIdx? = None
let mut descriptor : TypeIdx? = None
while true {
match buf.get(cursor) {
Some(0x4C) => {
if describes is Some(_) || descriptor is Some(_) {
return Err(BinaryDecodeError::InvalidCompType)
}
cursor = match
(
Decode::decode(buf, cursor + 1) :
Result[(TypeIdx, Int), BinaryDecodeError]) {
Ok((idx, next)) => {
describes = Some(idx)
next
}
Err(err) => return Err(err)
}
}
Some(0x4D) => {
if descriptor is Some(_) {
return Err(BinaryDecodeError::InvalidCompType)
}
cursor = match
(
Decode::decode(buf, cursor + 1) :
Result[(TypeIdx, Int), BinaryDecodeError]) {
Ok((idx, next)) => {
descriptor = Some(idx)
next
}
Err(err) => return Err(err)
}
}
_ => break
}
}
Ok((TypeMetadata::new(describes~, descriptor~), cursor))
}
///|
fn decode_shared_comptype(
buf : Bytes,
i : Int,
metadata : TypeMetadata,
) -> Result[(CompType, TypeMetadata, Int), BinaryDecodeError] {
let (cursor, metadata) = if buf.get(i) == Some(0x65) {
(i + 1, metadata.with_shared(true))
} else {
(i, metadata)
}
match Decode::decode(buf, cursor) {
Ok((ct, next)) => Ok((ct, metadata, next))
Err(err) => Err(err)
}
}
///|
fn decode_subtype_tail(
buf : Bytes,
i : Int,
) -> Result[(CompType, TypeMetadata, Int), BinaryDecodeError] {
let (cursor, shared) = if buf.get(i) == Some(0x65) {
(i + 1, true)
} else {
(i, false)
}
let (metadata, cursor) = match decode_descriptor_clauses(buf, cursor) {
Ok(value) => value
Err(err) => return Err(err)
}
let metadata = metadata.with_shared(shared)
match Decode::decode(buf, cursor) {
Ok((ct, next)) => Ok((ct, metadata, next))
Err(err) => Err(err)
}
}
///|
pub impl Decode for SubType with fn decode(buf, i) {
match buf.get(i) {
// Shared definition wrapper.
Some(0x65) =>
match
(Decode::decode(buf, i + 1) : Result[(SubType, Int), BinaryDecodeError]) {
Ok((SubType(f, supers, meta, ct), next)) =>
Ok(
(SubType::new(f, supers, ct, metadata=meta.with_shared(true)), next),
)
Ok((CompTypeSubType(meta, ct), next)) =>
Ok((SubType::comp_type(ct, metadata=meta.with_shared(true)), next))
Err(err) => Err(err)
}
// Final
Some(0x4F) =>
match Decode::decode(buf, i + 1) {
Ok((idxs, i)) =>
match decode_subtype_tail(buf, i) {
Ok((ct, meta, i)) =>
Ok((SubType::new(true, idxs, ct, metadata=meta), i))
Err(err) => Err(err)
}
Err(err) => Err(err)
}
// Subtypes
Some(0x50) =>
match Decode::decode(buf, i + 1) {
Ok((idxs, i)) =>
match decode_subtype_tail(buf, i) {
Ok((ct, meta, i)) =>
Ok((SubType::new(false, idxs, ct, metadata=meta), i))
Err(err) => Err(err)
}
Err(err) => Err(err)
}
// CompType, defer to comp type decoder
Some(_) => {
let (meta, next) = match decode_descriptor_clauses(buf, i) {
Ok(v) => v
Err(err) => return Err(err)
}
match decode_shared_comptype(buf, next, meta) {
Ok((ct, meta, i)) => Ok((SubType::comp_type(ct, metadata=meta), i))
Err(err) => Err(err)
}
}
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
// Private success storage avoids boxing a tuple and Result before each typed
// decoder immediately unpacks them. The public Decode result stays unchanged.
#valtype
priv struct UnsignedDecodeValue {
value : UInt64
next : Int
error : BinaryDecodeError?
}
///|
#inline
fn UnsignedDecodeValue::success(
value : UInt64,
next : Int,
) -> UnsignedDecodeValue {
{ value, next, error: None, }
}
///|
#inline
fn UnsignedDecodeValue::failure(
error : BinaryDecodeError,
) -> UnsignedDecodeValue {
{ value: 0UL, next: 0, error: Some(error), }
}
///|
fn decode_unsigned_value(
bytes : Bytes,
index : Int,
nbits : Int,
) -> UnsignedDecodeValue {
if nbits <= 0 || nbits > 64 {
return UnsignedDecodeValue::failure(
BinaryDecodeError::InvalidUnsignedLebBitWidth,
)
}
if index < 0 {
return UnsignedDecodeValue::failure(BinaryDecodeError::IndexOutOfBounds)
}
let max_bytes = max_leb_bytes(nbits)
let mut i = index
let mut shift = 0
let mut acc : UInt64 = 0UL
let mut count = 0
while true {
if i >= bytes.length() {
return UnsignedDecodeValue::failure(
BinaryDecodeError::UnexpectedEofInUnsignedLeb,
)
}
if count >= max_bytes {
return UnsignedDecodeValue::failure(
BinaryDecodeError::UnsignedLebTooManyBytes,
)
}
let byte_u : UInt64 = bytes[i].to_uint64()
i += 1
count += 1
let payload : UInt64 = byte_u & 0x7fUL
acc = acc | (payload << shift)
let cont = (byte_u & 0x80UL) != 0UL
shift = shift + 7
if !cont {
// range check
if nbits < 64 {
let max_val = (1UL << nbits) - 1UL
if acc > max_val {
return UnsignedDecodeValue::failure(
BinaryDecodeError::UnsignedLebOutOfRangeForBitWidth,
)
}
}
// terminal unused bits constraint - ONLY at max bytes
if count == max_bytes {
let rem = nbits % 7
if rem != 0 {
let limit = 1UL << rem
if payload >= limit {
return UnsignedDecodeValue::failure(
BinaryDecodeError::UnsignedLebTerminalHasNonZeroUnusedBits,
)
}
}
}
return UnsignedDecodeValue::success(acc, i)
}
}
UnsignedDecodeValue::failure(BinaryDecodeError::UnreachableDecodeState)
}
///|
fn decode_unsigned(
bytes : Bytes,
index : Int,
nbits : Int,
) -> Result[(UInt64, Int), BinaryDecodeError] {
let decoded = decode_unsigned_value(bytes, index, nbits)
match decoded.error {
Some(err) => Err(err)
None => Ok((decoded.value, decoded.next))
}
}
///|
fn decode_signed(
bytes : Bytes,
index : Int,
nbits : Int,
) -> Result[(Int64, Int), BinaryDecodeError] {
if nbits <= 0 || nbits > 64 {
return Err(BinaryDecodeError::InvalidSignedLebBitWidth)
}
if index < 0 {
return Err(BinaryDecodeError::IndexOutOfBounds)
}
let max_bytes = max_leb_bytes(nbits)
let mut i = index
let mut shift = 0
let mut acc : Int64 = 0
let mut count = 0
let mut last_byte : UInt64 = 0
while true {
if i >= bytes.length() {
return Err(BinaryDecodeError::UnexpectedEofInSignedLeb)
}
if count >= max_bytes {
return Err(BinaryDecodeError::SignedLebTooManyBytes)
}
let byte_u = bytes[i].to_uint64()
last_byte = byte_u
i += 1
count += 1
let payload = (byte_u & 0x7f).reinterpret_as_int64()
acc = acc | (payload << shift)
let cont = (byte_u & 0x80) != 0
shift += 7
if !cont {
break
}
}
// sign extend to full int64 based on last byte's sign bit (0x40)
if (last_byte & 0x40) != 0 && shift < 64 {
acc = acc | ((-1 : Int64) << shift)
}
// range check for N bits signed
if nbits < 64 {
let min = (-1 : Int64) << (nbits - 1)
let max = ((1 : Int64) << (nbits - 1)) - 1
if acc < min || acc > max {
return Err(BinaryDecodeError::SignedLebOutOfRangeForBitWidth)
}
}
// terminal-byte unused bits constraint - ONLY at max bytes
if count == max_bytes {
let rem = nbits % 7
if rem != 0 {
let payload_u = last_byte & 0x7f
let used_mask = (1UL << rem) - 1UL
let inv_used = UInt64::lnot(used_mask) & 0x7fUL
let unused = payload_u & inv_used
if acc >= 0 {
if unused != 0 {
return Err(
BinaryDecodeError::SignedLebPositiveTerminalHasNonZeroUnusedBits,
)
}
} else {
let want = inv_used
if unused != want {
return Err(
BinaryDecodeError::SignedLebTerminalHasWrongSignExtensionBits,
)
}
}
}
}
Ok((acc, i))
}
///|
pub impl Decode for S33 with fn decode(bytes, i) {
match decode_signed(bytes, i, 33) {
Err(err) => Err(err)
Ok((val, i)) if val >= 0 && val <= 4294967295 =>
Ok((S33(val.to_int().reinterpret_as_uint()), i))
Ok(_) => Err(BinaryDecodeError::InvalidS33Range)
}
}
///|
pub impl Decode for I32 with fn decode(bytes, i) {
match decode_signed(bytes, i, 32) {
Err(err) => Err(err)
Ok((val, i)) => Ok((I32(val.to_int()), i))
}
}
///|
pub impl Decode for @lib.U32 with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((U32(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for I64 with fn decode(bytes, i) {
match decode_signed(bytes, i, 64) {
Err(err) => Err(err)
Ok((val, i)) => Ok((I64(val), i))
}
}
///|
pub impl Decode for @lib.U64 with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 64)
match decoded.error {
Some(err) => Err(err)
None => Ok((U64(decoded.value), decoded.next))
}
}
///|
pub impl Decode for F32 with fn decode(bytes, i) {
if i >= 0 && i <= bytes.length() && bytes.length() - i >= 4 {
let value : Int = (bytes.unsafe_get(i + 3).to_int() << 24) |
(bytes.unsafe_get(i + 2).to_int() << 16) |
(bytes.unsafe_get(i + 1).to_int() << 8) |
bytes.unsafe_get(i).to_int()
Ok((F32(Float::reinterpret_from_int(value)), i + 4))
} else {
Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
pub impl Decode for F64 with fn decode(bytes, i) {
if i >= 0 && i <= bytes.length() && bytes.length() - i >= 8 {
let value : Int64 = (bytes.unsafe_get(i + 7).to_int64() << 56) |
(bytes.unsafe_get(i + 6).to_int64() << 48) |
(bytes.unsafe_get(i + 5).to_int64() << 40) |
(bytes.unsafe_get(i + 4).to_int64() << 32) |
(bytes.unsafe_get(i + 3).to_int64() << 24) |
(bytes.unsafe_get(i + 2).to_int64() << 16) |
(bytes.unsafe_get(i + 1).to_int64() << 8) |
bytes.unsafe_get(i).to_int64()
Ok((F64(value.reinterpret_as_double()), i + 8))
} else {
Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
pub impl Decode for Bool with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x00) => Ok((false, i + 1))
Some(0x01) => Ok((true, i + 1))
Some(_) => Err(BinaryDecodeError::InvalidBoolByte)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
pub impl[T : Decode] Decode for T? with fn decode(bytes, i) {
match T::decode(bytes, i) {
Err(_) => Ok((None, i))
Ok((val, i)) => Ok((Some(val), i))
}
}
///|
pub impl Decode for TypeIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((TypeIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for FuncIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((FuncIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for TableIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((TableIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for MemIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((MemIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for GlobalIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((GlobalIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for TagIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((TagIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for ElemIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((ElemIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for DataIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((DataIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for LocalIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((LocalIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for LaneIdx with fn decode(bytes, i) {
if bytes.get(i) is Some(n) && n < 16 {
Ok((LaneIdx::new(n), i + 1))
} else {
Err(BinaryDecodeError::InvalidLaneIndex)
}
}
///|
pub impl Decode for LabelIdx with fn decode(bytes, i) {
let decoded = decode_unsigned_value(bytes, i, 32)
match decoded.error {
Some(err) => Err(err)
None => Ok((LabelIdx::new(decoded.value.to_uint()), decoded.next))
}
}
///|
pub impl Decode for Name with fn decode(bytes, i) {
let (@lib.U32(len_u), j) = match Decode::decode(bytes, i) {
Err(err) => return Err(err)
Ok(t) => t
}
let len = len_u.reinterpret_as_int()
if len < 0 {
return Err(BinaryDecodeError::NegativeNameLength)
}
if len > bytes.length() - j {
return Err(BinaryDecodeError::IndexOutOfBounds)
}
let end = j + len
let name = @utf8.decode(bytes[j:end]) catch {
_ => return Err(BinaryDecodeError::InvalidUtf8Name)
}
Ok((Name::new(name.to_string_view()), end))
}
///|
pub impl Decode for NameAssoc with fn decode(bytes, i) {
let (@lib.U32(idx), i) = match Decode::decode(bytes, i) {
Ok(t) => t
Err(err) => return Err(err)
}
let (name, i) = match Decode::decode(bytes, i) {
Ok(t) => t
Err(err) => return Err(err)
}
Ok((NameAssoc::new(idx, name), i))
}
///|
pub impl Decode for NameMap with fn decode(bytes, i) {
let (@lib.U32(len_u), i) = match Decode::decode(bytes, i) {
Ok(t) => t
Err(err) => return Err(err)
}
let entries : Array[NameAssoc] = []
let mut next = i
let mut prev_idx : UInt? = None
let mut remaining = len_u
while remaining > 0U {
let (entry, decoded_next) = match
(Decode::decode(bytes, next) : Result[(NameAssoc, Int), BinaryDecodeError]) {
Ok(t) => t
Err(err) => return Err(err)
}
let idx = entry.0
match prev_idx {
Some(prev) if idx <= prev =>
return Err(BinaryDecodeError::InvalidNameMapOrder)
_ => ()
}
prev_idx = Some(idx)
entries.push(entry)
next = decoded_next
remaining = remaining - 1U
}
Ok((NameMap::new(entries), next))
}
///|
pub impl Decode for IndirectNameAssoc with fn decode(bytes, i) {
let (@lib.U32(idx), i) = match Decode::decode(bytes, i) {
Ok(t) => t
Err(err) => return Err(err)
}
let (names, i) = match Decode::decode(bytes, i) {
Ok(t) => t
Err(err) => return Err(err)
}
Ok((IndirectNameAssoc::new(idx, names), i))
}
///|
pub impl Decode for IndirectNameMap with fn decode(bytes, i) {
let (@lib.U32(len_u), i) = match Decode::decode(bytes, i) {
Ok(t) => t
Err(err) => return Err(err)
}
let entries : Array[IndirectNameAssoc] = []
let mut next = i
let mut prev_idx : UInt? = None
let mut remaining = len_u
while remaining > 0U {
let (entry, decoded_next) = match
(
Decode::decode(bytes, next) :
Result[(IndirectNameAssoc, Int), BinaryDecodeError]) {
Ok(t) => t
Err(err) => return Err(err)
}
let idx = entry.0
match prev_idx {
Some(prev) if idx <= prev =>
return Err(BinaryDecodeError::InvalidNameMapOrder)
_ => ()
}
prev_idx = Some(idx)
entries.push(entry)
next = decoded_next
remaining = remaining - 1U
}
Ok((IndirectNameMap::new(entries), next))
}
///|
fn[T : Decode] decode_name_subsection_payload(
bytes : Bytes,
payload_start : Int,
payload_end : Int,
) -> Result[T, BinaryDecodeError] {
let (decoded, consumed) = match Decode::decode(bytes, payload_start) {
Ok(t) => t
Err(err) => return Err(err)
}
if consumed != payload_end {
return Err(BinaryDecodeError::InvalidSectionPayloadTrailingBytes)
}
Ok(decoded)
}
///|
pub impl Decode for NameSec with fn decode(bytes, i) {
let mut next = i
let mut prev_subsection_id : Byte? = None
let mut module_name : Name? = None
let mut func_names : NameMap? = None
let mut local_names : IndirectNameMap? = None
let mut label_names : IndirectNameMap? = None
let mut type_names : NameMap? = None
let mut table_names : NameMap? = None
let mut memory_names : NameMap? = None
let mut global_names : NameMap? = None
let mut elem_names : NameMap? = None
let mut data_names : NameMap? = None
let mut field_names : IndirectNameMap? = None
let mut tag_names : NameMap? = None
while next < bytes.length() {
let subsection_id = match bytes.get(next) {
Some(id) => id
None => break
}
// Unknown optional subsections do not change the order of known names.
if subsection_id <= 11 {
match prev_subsection_id {
Some(prev) if subsection_id <= prev =>
return Err(BinaryDecodeError::InvalidNameSubsectionOrder)
_ => ()
}
prev_subsection_id = Some(subsection_id)
}
let (@lib.U32(payload_len_u), payload_start) = match
Decode::decode(bytes, next + 1) {
Ok(t) => t
Err(err) => return Err(err)
}
if payload_len_u > (bytes.length() - payload_start).reinterpret_as_uint() {
return Err(BinaryDecodeError::SectionPayloadLengthOutOfRange)
}
let payload_end = payload_start + payload_len_u.reinterpret_as_int()
match subsection_id {
0 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(name) => module_name = Some(name)
Err(err) => return Err(err)
}
1 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => func_names = Some(names)
Err(err) => return Err(err)
}
2 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => local_names = Some(names)
Err(err) => return Err(err)
}
3 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => label_names = Some(names)
Err(err) => return Err(err)
}
4 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => type_names = Some(names)
Err(err) => return Err(err)
}
5 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => table_names = Some(names)
Err(err) => return Err(err)
}
6 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => memory_names = Some(names)
Err(err) => return Err(err)
}
7 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => global_names = Some(names)
Err(err) => return Err(err)
}
8 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => elem_names = Some(names)
Err(err) => return Err(err)
}
9 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => data_names = Some(names)
Err(err) => return Err(err)
}
10 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => field_names = Some(names)
Err(err) => return Err(err)
}
11 =>
match
decode_name_subsection_payload(bytes, payload_start, payload_end) {
Ok(names) => tag_names = Some(names)
Err(err) => return Err(err)
}
_ => ()
}
next = payload_end
}
Ok(
(
NameSec::new(
module_name~,
func_names~,
local_names~,
label_names~,
type_names~,
table_names~,
memory_names~,
global_names~,
elem_names~,
data_names~,
field_names~,
tag_names~,
),
next,
),
)
}
///|
fn[T : Decode] decode_section_vector_payload(
bytes : Bytes,
i : Int,
section_id : Byte,
) -> Result[(Array[T], Int), BinaryDecodeError] {
if bytes.get(i) != Some(section_id) {
return Err(BinaryDecodeError::InvalidSectionHeader)
}
let (@lib.U32(len_u), payload_start) = match Decode::decode(bytes, i + 1) {
Ok(t) => t
Err(t) => return Err(t)
}
if len_u > (bytes.length() - payload_start).reinterpret_as_uint() {
return Err(BinaryDecodeError::SectionPayloadLengthOutOfRange)
}
let payload_end = payload_start + len_u.reinterpret_as_int()
let (content, consumed) = match Decode::decode(bytes, payload_start) {
Ok(t) => t
Err(t) => return Err(t)
}
if consumed == payload_end {
Ok((content, payload_end))
} else {
Err(BinaryDecodeError::InvalidSectionPayloadTrailingBytes)
}
}
///|
fn[T : Decode] decode_section_payload(
bytes : Bytes,
i : Int,
section_id : Byte,
) -> Result[(T, Int), BinaryDecodeError] {
if bytes.get(i) != Some(section_id) {
return Err(BinaryDecodeError::InvalidSectionHeader)
}
let (@lib.U32(len_u), payload_start) = match Decode::decode(bytes, i + 1) {
Ok(t) => t
Err(t) => return Err(t)
}
if len_u > (bytes.length() - payload_start).reinterpret_as_uint() {
return Err(BinaryDecodeError::SectionPayloadLengthOutOfRange)
}
let payload_end = payload_start + len_u.reinterpret_as_int()
let (content, consumed) = match Decode::decode(bytes, payload_start) {
Ok(t) => t
Err(t) => return Err(t)
}
if consumed == payload_end {
Ok((content, payload_end))
} else {
Err(BinaryDecodeError::InvalidSectionPayloadTrailingBytes)
}
}
///|
fn module_section_span(bytes : Bytes, section_start : Int) -> (Int, Int) {
if section_start < 0 || section_start >= bytes.length() {
return (section_start, 0)
}
let len_result : Result[(@lib.U32, Int), BinaryDecodeError] = Decode::decode(
bytes,
section_start + 1,
)
match len_result {
Ok((@lib.U32(payload_len_u), payload_start)) => {
let remaining = bytes.length() - payload_start
let section_end = if payload_len_u <= remaining.reinterpret_as_uint() {
payload_start + payload_len_u.reinterpret_as_int()
} else {
bytes.length()
}
(section_start, section_end - section_start)
}
Err(_) => (section_start, bytes.length() - section_start)
}
}
///|
fn module_decode_error(
err : BinaryDecodeError,
section_id? : Int? = None,
section_offset? : Int? = None,
section_len? : Int? = None,
trailing_offset? : Int? = None,
) -> ModuleDecodeErrorDetail {
{ err, section_id, section_offset, section_len, trailing_offset, }
}
///|
fn module_section_decode_error(
bytes : Bytes,
section_start : Int,
err : BinaryDecodeError,
) -> ModuleDecodeErrorDetail {
let (offset, len) = module_section_span(bytes, section_start)
let section_id = bytes.get(section_start).map(fn(id) { id.to_int() })
module_decode_error(
err,
section_id~,
section_offset=Some(offset),
section_len=Some(len),
)
}
///|
fn decode_custom_sections_with_detail(
bytes : Bytes,
i : Int,
out : Array[CustomSec],
name_out : Array[NameSec],
name_payload_out : Array[Bytes],
) -> Result[Int, ModuleDecodeErrorDetail] {
let mut i = i
while bytes.get(i) == Some(0) {
let section_start = i
match decode_custom_section_header(bytes, i) {
Ok((name, payload_start, next)) => {
let payload = bytes[payload_start:next].to_owned()
if name == Name::new("name") {
if name_out.length() > 0 {
return Err(
module_section_decode_error(
bytes,
section_start,
BinaryDecodeError::DuplicateNameSection,
),
)
}
match Decode::decode(payload, 0) {
Ok((name_sec, consumed)) => {
if consumed != payload.length() {
return Err(
module_section_decode_error(
bytes,
section_start,
BinaryDecodeError::InvalidSectionPayloadTrailingBytes,
),
)
}
name_out.push(name_sec)
name_payload_out.push(payload)
}
Err(err) =>
return Err(module_section_decode_error(bytes, section_start, err))
}
} else if name == Name::new("compiler.facts") {
if out.any(fn(section) {
let CustomSec(existing_name, _) = section
existing_name == Name::new("compiler.facts")
}) {
return Err(
module_section_decode_error(
bytes,
section_start,
BinaryDecodeError::DuplicateCompilerFactsSection,
),
)
}
match
(
Decode::decode(payload, 0) :
Result[(CompilerFactCustomSection, Int), BinaryDecodeError]) {
Ok((_, consumed)) => {
if consumed != payload.length() {
return Err(
module_section_decode_error(
bytes,
section_start,
BinaryDecodeError::CompilerFactsTrailingBytes,
),
)
}
out.push(CustomSec::new(name, payload))
}
Err(err) =>
return Err(
module_section_decode_error(
bytes,
section_start,
compiler_facts_payload_error(err),
),
)
}
} else {
out.push(CustomSec::new(name, payload))
}
i = next
}
Err(err) =>
return Err(module_section_decode_error(bytes, section_start, err))
}
}
Ok(i)
}
///|
fn decode_custom_section_header(
bytes : Bytes,
i : Int,
) -> Result[(Name, Int, Int), BinaryDecodeError] {
if bytes.get(i) != Some(0) {
return Err(BinaryDecodeError::InvalidSectionHeader)
}
let (@lib.U32(len), i1) = match Decode::decode(bytes, i + 1) {
Ok(t) => t
Err(t) => return Err(t)
}
if len > (bytes.length() - i1).reinterpret_as_uint() {
return Err(BinaryDecodeError::CustomSectionPayloadLengthOutOfRange)
}
let end = i1 + len.reinterpret_as_int()
let (name, payload_start) = match Decode::decode(bytes, i1) {
Ok(t) => t
Err(t) => return Err(t)
}
if payload_start > end {
return Err(BinaryDecodeError::CustomSectionPayloadLengthOutOfRange)
}
Ok((name, payload_start, end))
}
///|
fn[T : Decode] decode_optional_section_with_detail(
bytes : Bytes,
i : Int,
section_id : Byte,
) -> Result[(T?, Int), ModuleDecodeErrorDetail] {
if bytes.get(i) != Some(section_id) {
return Ok((None, i))
}
let section_start = i
match Decode::decode(bytes, i) {
Ok((sec, next)) => Ok((Some(sec), next))
Err(err) => Err(module_section_decode_error(bytes, section_start, err))
}
}
///|
pub fn decode_module_with_detail(
bytes : Bytes,
i : Int,
) -> Result[(Module, Int), ModuleDecodeErrorDetail] {
let mut i = i
let custom = Array::new()
let name_secs = Array::new()
let name_payloads = Array::new()
let mut mod = Module::new()
for b in [0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00] {
if bytes.get(i) != Some(b.to_byte()) {
return Err(module_decode_error(BinaryDecodeError::InvalidMagicHeader))
}
i = i + 1
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (type_sec, next) = match
decode_optional_section_with_detail(bytes, i, 1) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if type_sec is Some(sec) {
mod = mod.with_type_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (import_sec, next) = match
decode_optional_section_with_detail(bytes, i, 2) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if import_sec is Some(sec) {
mod = mod.with_import_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (func_sec, next) = match
decode_optional_section_with_detail(bytes, i, 3) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if func_sec is Some(sec) {
mod = mod.with_func_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (table_sec, next) = match
decode_optional_section_with_detail(bytes, i, 4) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if table_sec is Some(sec) {
mod = mod.with_table_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (mem_sec, next) = match decode_optional_section_with_detail(bytes, i, 5) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if mem_sec is Some(sec) {
mod = mod.with_mem_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (tag_sec, next) = match
decode_optional_section_with_detail(bytes, i, 13) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if tag_sec is Some(sec) {
mod = mod.with_tag_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (stringrefs_sec, next) = match
(
decode_optional_section_with_detail(bytes, i, 14) :
Result[(StringRefsSec?, Int), ModuleDecodeErrorDetail]) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
let stringrefs_ctx = match stringrefs_sec {
Some(sec) => {
let StringRefsSec(strings) = sec
mod = mod.with_stringrefs_sec(sec)
Some(strings)
}
None => None
}
let tail = with_binary_decode_stringrefs_context(stringrefs_ctx, fn() {
let mut i = i
let mut mod = mod
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (global_sec, next) = match
decode_optional_section_with_detail(bytes, i, 6) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if global_sec is Some(sec) {
mod = mod.with_global_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (export_sec, next) = match
decode_optional_section_with_detail(bytes, i, 7) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if export_sec is Some(sec) {
mod = mod.with_export_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (start_sec, next) = match
decode_optional_section_with_detail(bytes, i, 8) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if start_sec is Some(sec) {
mod = mod.with_start_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (elem_sec, next) = match
decode_optional_section_with_detail(bytes, i, 9) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if elem_sec is Some(sec) {
mod = mod.with_elem_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (data_cnt_sec, next) = match
decode_optional_section_with_detail(bytes, i, 12) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if data_cnt_sec is Some(sec) {
mod = mod.with_data_cnt_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (code_sec, next) = match
decode_optional_section_with_detail(bytes, i, 10) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if code_sec is Some(sec) {
mod = mod.with_code_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
let (data_sec, next) = match
decode_optional_section_with_detail(bytes, i, 11) {
Ok(t) => t
Err(detail) => return Err(detail)
}
i = next
if data_sec is Some(sec) {
mod = mod.with_data_sec(sec)
}
i = match
decode_custom_sections_with_detail(
bytes, i, custom, name_secs, name_payloads,
) {
Ok(next) => next
Err(detail) => return Err(detail)
}
Ok((mod, i))
})
let tail_result = match tail {
Ok(result) => result
Err(detail) => return Err(detail)
}
let tail_mod = tail_result.0
let tail_i = tail_result.1
mod = tail_mod
i = tail_i
let ordinary_custom : Array[CustomSec] = []
for section in custom {
let CustomSec(name, payload) = section
if name == Name::new("compiler.facts") {
match
(
Decode::decode(payload, 0) :
Result[(CompilerFactCustomSection, Int), BinaryDecodeError]) {
Ok((facts, _)) => mod = mod.with_compiler_fact_custom_section(facts)
Err(err) => return Err(module_decode_error(err))
}
} else {
ordinary_custom.push(section)
}
}
mod = mod.with_custom_secs(ordinary_custom)
match name_secs.get(0) {
Some(name_sec) => {
mod = mod.with_name_sec(name_sec)
match name_payloads.get(0) {
Some(payload) => mod = mod.with_raw_name_sec_payload(payload)
None => ()
}
}
None => ()
}
if i == bytes.length() {
Ok((mod, i))
} else {
Err(
module_decode_error(
BinaryDecodeError::InvalidModule,
trailing_offset=Some(i),
),
)
}
}
///|
pub impl Decode for Module with fn decode(bytes, i) {
match decode_module_with_detail(bytes, i) {
Ok(t) => Ok(t)
Err(detail) => Err(detail.err)
}
}
///|
pub impl Decode for Elem with fn decode(bytes, i) {
let is_funcref = fn(rt : RefType) {
rt == RefType::abs(AbsHeapType::func()) ||
rt == RefType::new(true, HeapType::abs(AbsHeapType::func()))
}
let (header, next) = match
(Decode::decode(bytes, i) : Result[(@lib.U32, Int), BinaryDecodeError]) {
Ok((@lib.U32(v), next)) => (v, next)
Err(t) => return Err(t)
}
match header {
0U =>
match Decode::decode(bytes, next) {
Ok((expr, i)) =>
match Decode::decode(bytes, i) {
Ok((fidxs, i)) =>
Ok(
(
Elem::new(
ElemMode::active(TableIdx::new(0), expr),
ElemKind::funcs(fidxs),
),
i,
),
)
Err(t) => Err(t)
}
Err(t) => Err(t)
}
1U =>
match bytes.get(next) {
Some(0x00) =>
match Decode::decode(bytes, next + 1) {
Ok((fidxs, i)) =>
Ok((Elem::new(ElemMode::passive(), ElemKind::funcs(fidxs)), i))
Err(t) => Err(t)
}
_ => Err(BinaryDecodeError::InvalidElemHeader)
}
2U =>
match Decode::decode(bytes, next) {
Ok((@lib.TableIdx(idx), i)) =>
match Decode::decode(bytes, i) {
Ok((expr, i)) =>
match bytes.get(i) {
Some(0x00) =>
match Decode::decode(bytes, i + 1) {
Ok((fidxs, i)) =>
Ok(
(
Elem::new(
ElemMode::active(TableIdx::new(idx), expr),
ElemKind::funcs(fidxs),
),
i,
),
)
Err(t) => Err(t)
}
_ => Err(BinaryDecodeError::InvalidElemHeader)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
3U =>
match bytes.get(next) {
Some(0x00) =>
match Decode::decode(bytes, next + 1) {
Ok((fidxs, i)) =>
Ok(
(Elem::new(ElemMode::declarative(), ElemKind::funcs(fidxs)), i),
)
Err(t) => Err(t)
}
_ => Err(BinaryDecodeError::InvalidElemHeader)
}
4U =>
match Decode::decode(bytes, next) {
Ok((expr, i)) =>
match Decode::decode(bytes, i) {
Ok((exprs, i)) =>
Ok(
(
Elem::new(
ElemMode::active(TableIdx::new(0), expr),
ElemKind::func_exprs(exprs),
),
i,
),
)
Err(t) => Err(t)
}
Err(t) => Err(t)
}
5U =>
match Decode::decode(bytes, next) {
Ok((rt, i)) =>
match Decode::decode(bytes, i) {
Ok((exprs, i)) =>
Ok(
(
Elem::new(
ElemMode::passive(),
ElemKind::typed_exprs(rt, exprs),
),
i,
),
)
Err(t) => Err(t)
}
Err(t) => Err(t)
}
6U =>
match Decode::decode(bytes, next) {
Ok((idx, i)) =>
match Decode::decode(bytes, i) {
Ok((expr, i)) =>
match
(
Decode::decode(bytes, i) :
Result[(RefType, Int), BinaryDecodeError]) {
Ok((rt, i)) =>
match
(
Decode::decode(bytes, i) :
Result[(Array[Expr], Int), BinaryDecodeError]) {
Ok((exprs, i)) => {
let kind = if is_funcref(rt) {
ElemKind::func_exprs(exprs)
} else {
ElemKind::typed_exprs(rt, exprs)
}
Ok((Elem::new(ElemMode::active(idx, expr), kind), i))
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
7U =>
match Decode::decode(bytes, next) {
Ok((rt, i)) =>
match Decode::decode(bytes, i) {
Ok((exprs, i)) =>
Ok(
(
Elem::new(
ElemMode::declarative(),
ElemKind::typed_exprs(rt, exprs),
),
i,
),
)
Err(t) => Err(t)
}
Err(t) => Err(t)
}
_ => Err(BinaryDecodeError::InvalidElemHeader)
}
}
///|
pub impl Decode for ElemSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 9) {
Ok((content, next)) => Ok((ElemSec::new(content), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for DataCntSec with fn decode(bytes, i) {
match
(
decode_section_payload(bytes, i, 12) :
Result[(@lib.U32, Int), BinaryDecodeError]) {
Ok((count, i)) => Ok((DataCntSec::new(count), i))
Err(t) => Err(t)
}
}
///|
pub impl Decode for LocalRun with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Ok((@lib.U32(count), i)) =>
match Decode::decode(bytes, i) {
Ok((vt, i)) => Ok((LocalRun::new(count, vt), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
}
///|
pub impl Decode for Locals with fn decode(bytes, i) {
match
(
Decode::decode(bytes, i) :
Result[(Array[@lib.LocalRun], Int), BinaryDecodeError]) {
Ok((runs, i)) => Ok((Locals::new(runs), i))
Err(t) => Err(t)
}
}
///|
pub impl Decode for Func with fn decode(bytes, i) {
let (@lib.U32(size), body_start) = match Decode::decode(bytes, i) {
Ok(t) => t
Err(t) => return Err(t)
}
if size > (bytes.length() - body_start).reinterpret_as_uint() {
return Err(BinaryDecodeError::SectionPayloadLengthOutOfRange)
}
let body_end = body_start + size.reinterpret_as_int()
// A body needs a local-run count and its expression terminator.
if size < 2U {
return Err(BinaryDecodeError::InvalidModule)
}
let (locals, expr_start) = match
(
Decode::decode(bytes, body_start) :
Result[(Array[@lib.LocalRun], Int), BinaryDecodeError]) {
Ok(t) => t
Err(t) => return Err(t)
}
if expr_start >= body_end {
return Err(BinaryDecodeError::InvalidSectionPayloadTrailingBytes)
}
let mut total_locals : UInt64 = 0UL
for local_entry in locals {
total_locals += local_entry.count.to_uint64()
if total_locals > 4294967295UL {
return Err(BinaryDecodeError::InvalidModule)
}
}
let (expr, next) = match Decode::decode(bytes, expr_start) {
Ok(t) => t
Err(t) => return Err(t)
}
if next != body_end {
return Err(BinaryDecodeError::InvalidSectionPayloadTrailingBytes)
}
Ok((Func::new(Locals::new(locals), expr), next))
}
///|
pub impl Decode for CodeSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 10) {
Ok((funcs, next)) => Ok((CodeSec::new(funcs), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for Data with fn decode(bytes, i) {
let (header, next) = match
(Decode::decode(bytes, i) : Result[(@lib.U32, Int), BinaryDecodeError]) {
Ok((@lib.U32(v), next)) => (v, next)
Err(t) => return Err(t)
}
match header {
0U =>
match Decode::decode(bytes, next) {
Ok((expr, i)) =>
match Decode::decode(bytes, i) {
Ok((bytes, i)) =>
Ok((Data::new(DataMode::active(MemIdx::new(0), expr), bytes), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
1U =>
match Decode::decode(bytes, next) {
Ok((bytes, i)) => Ok((Data::new(DataMode::passive(), bytes), i))
Err(t) => Err(t)
}
2U =>
match Decode::decode(bytes, next) {
Ok((idx, i)) =>
match Decode::decode(bytes, i) {
Ok((expr, i)) =>
match Decode::decode(bytes, i) {
Ok((bytes, i)) =>
Ok((Data::new(DataMode::active(idx, expr), bytes), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
_ => Err(BinaryDecodeError::InvalidDataHeader)
}
}
///|
pub impl Decode for DataSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 11) {
Ok((content, next)) => Ok((DataSec::new(content), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for StringRefsSec with fn decode(bytes, i) {
if bytes.get(i) != Some(14) {
return Err(BinaryDecodeError::InvalidSectionHeader)
}
let (@lib.U32(len_u), payload_start) = match Decode::decode(bytes, i + 1) {
Ok(t) => t
Err(t) => return Err(t)
}
if len_u > (bytes.length() - payload_start).reinterpret_as_uint() {
return Err(BinaryDecodeError::SectionPayloadLengthOutOfRange)
}
let payload_end = payload_start + len_u.reinterpret_as_int()
if payload_start == payload_end || bytes[payload_start] != 0x00 {
return Err(BinaryDecodeError::InvalidStringRefSection)
}
match
(
Decode::decode(bytes, payload_start + 1) :
Result[(Array[Bytes], Int), BinaryDecodeError]) {
Ok((strings, consumed)) =>
if consumed == payload_end {
Ok((StringRefsSec::new(strings), payload_end))
} else {
Err(BinaryDecodeError::InvalidStringRefSection)
}
Err(err) => Err(err)
}
}
///|
pub impl Decode for CustomSec with fn decode(bytes, i) {
match decode_custom_section_header(bytes, i) {
Ok((name, payload_start, end)) =>
Ok((CustomSec::new(name, bytes[payload_start:end].to_owned()), end))
Err(err) => Err(err)
}
}
///|
pub impl Decode for TypeSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 1) {
Ok((content, next)) => Ok((TypeSec::new(content), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for Import with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Ok((nm1, i)) =>
match Decode::decode(bytes, i) {
Ok((nm2, i)) =>
match Decode::decode(bytes, i) {
Ok((et, i)) => Ok((Import::new(nm1, nm2, et), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
}
///|
pub impl Decode for Limits with fn decode(bytes, i) {
match bytes.get(i) {
None => Err(BinaryDecodeError::IndexOutOfBounds)
Some(0x00) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(n), i)) => Ok((Limits::i32(n, None), i))
Err(t) => Err(t)
}
Some(0x01) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(n), i)) =>
match Decode::decode(bytes, i) {
Ok((@lib.U32(m), i)) => Ok((Limits::i32(n, Some(m)), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0x04) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U64(n), i)) => Ok((Limits::i64(n, None), i))
Err(t) => Err(t)
}
Some(0x05) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U64(n), i)) =>
match Decode::decode(bytes, i) {
Ok((@lib.U64(m), i)) => Ok((Limits::i64(n, Some(m)), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(_) => Err(BinaryDecodeError::InvalidLimits)
}
}
///|
pub impl Decode for TableType with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Ok((rt, i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((TableType::new(rt, l), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
}
///|
pub impl Decode for MemType with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x00) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(min), next)) =>
Ok((MemType::new(Limits::i32(min, None)), next))
Err(t) => Err(t)
}
Some(0x01) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(min), next)) =>
match Decode::decode(bytes, next) {
Ok((@lib.U32(max), end)) =>
Ok((MemType::new(Limits::i32(min, Some(max))), end))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0x02) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(min), next)) =>
Ok((MemType::new(Limits::i32(min, None), shared=true), next))
Err(t) => Err(t)
}
Some(0x03) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(min), next)) =>
match Decode::decode(bytes, next) {
Ok((@lib.U32(max), end)) =>
Ok((MemType::new(Limits::i32(min, Some(max)), shared=true), end))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0x04) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U64(min), next)) =>
Ok((MemType::new(Limits::i64(min, None)), next))
Err(t) => Err(t)
}
Some(0x05) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U64(min), next)) =>
match Decode::decode(bytes, next) {
Ok((@lib.U64(max), end)) =>
Ok((MemType::new(Limits::i64(min, Some(max))), end))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0x06) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U64(min), next)) =>
Ok((MemType::new(Limits::i64(min, None), shared=true), next))
Err(t) => Err(t)
}
Some(0x07) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U64(min), next)) =>
match Decode::decode(bytes, next) {
Ok((@lib.U64(max), end)) =>
Ok((MemType::new(Limits::i64(min, Some(max)), shared=true), end))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(_) => Err(BinaryDecodeError::InvalidLimits)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
pub impl Decode for GlobalType with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Ok((vt, i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((GlobalType::new(vt, m), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
}
///|
pub impl Decode for TagType with fn decode(bytes, i) {
if bytes.get(i) != Some(0x00) {
return Err(BinaryDecodeError::InvalidTagType)
}
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((TagType::new(idx), i))
Err(t) => Err(t)
}
}
///|
pub impl Decode for ExternType with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x00) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((ExternType::func(idx), i))
Err(t) => Err(t)
}
Some(0x01) =>
match Decode::decode(bytes, i + 1) {
Ok((tt, i)) => Ok((ExternType::table(tt), i))
Err(t) => Err(t)
}
Some(0x02) =>
match Decode::decode(bytes, i + 1) {
Ok((mt, i)) => Ok((ExternType::mem(mt), i))
Err(t) => Err(t)
}
Some(0x03) =>
match Decode::decode(bytes, i + 1) {
Ok((gt, i)) => Ok((ExternType::global(gt), i))
Err(t) => Err(t)
}
Some(0x04) =>
match Decode::decode(bytes, i + 1) {
Ok((tt, i)) => Ok((ExternType::tag(tt), i))
Err(t) => Err(t)
}
Some(_) => Err(BinaryDecodeError::InvalidExternTypeHeader)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
// General pattern for section decoding
///|
pub impl Decode for ImportSec with fn decode(bytes, i) {
if bytes.get(i) != Some(2) {
return Err(BinaryDecodeError::InvalidSectionHeader)
}
let (U32(len), start) = match Decode::decode(bytes, i + 1) {
Ok(value) => value
Err(err) => return Err(err)
}
if len > (bytes.length() - start).reinterpret_as_uint() {
return Err(BinaryDecodeError::SectionPayloadLengthOutOfRange)
}
let end = start + len.reinterpret_as_int()
// Bound every nested string/type/vector read to this section.
let payload = bytes[start:end].to_owned()
let (U32(count), after_count) = match Decode::decode(payload, 0) {
Ok(value) => value
Err(err) => return Err(err)
}
let imports : Array[Import] = []
let mut next = after_count
for _ in 0U.. value
Err(err) => return Err(err)
}
let (field_name, after_field) : (Name, Int) = match
Decode::decode(payload, after_module) {
Ok(value) => value
Err(err) => return Err(err)
}
let kind = payload.get(after_field)
if field_name == Name::new("") && (kind == Some(0x7f) || kind == Some(0x7e)) {
next = after_field + 1
let common_type : ExternType? = if kind == Some(0x7e) {
let (ty, after_type) = match Decode::decode(payload, next) {
Ok(value) => value
Err(err) => return Err(err)
}
next = after_type
Some(ty)
} else {
None
}
let (U32(group_count), after_group_count) = match
Decode::decode(payload, next) {
Ok(value) => value
Err(err) => return Err(err)
}
next = after_group_count
for _ in 0U.. value
Err(err) => return Err(err)
}
next = after_name
let ty = match common_type {
Some(ty) => ty
None => {
let (ty, after_type) = match Decode::decode(payload, next) {
Ok(value) => value
Err(err) => return Err(err)
}
next = after_type
ty
}
}
imports.push(Import::new(module_name, name, ty))
}
} else {
let (ty, after_type) = match Decode::decode(payload, after_field) {
Ok(value) => value
Err(err) => return Err(err)
}
imports.push(Import::new(module_name, field_name, ty))
next = after_type
}
}
if next != payload.length() {
Err(BinaryDecodeError::InvalidSectionPayloadTrailingBytes)
} else {
Ok((ImportSec::new(imports), end))
}
}
///|
pub impl Decode for FuncSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 3) {
Ok((content, next)) => Ok((FuncSec::new(content), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for BlockType with fn decode(bytes, i) {
if bytes.get(i) is Some(0x40) {
return Ok((BlockType::void_(), i + 1))
}
if Decode::decode(bytes, i) is Ok((vt, i)) {
return Ok((BlockType::val_type(vt), i))
}
if Decode::decode(bytes, i) is Ok((@lib.S33(idx), i)) {
return Ok((BlockType::type_idx(TypeIdx::new(idx)), i))
}
Err(BinaryDecodeError::InvalidBlockType)
}
///|
const MAX_INSTRUCTION_NESTING_DEPTH : Int = 20000
///|
fn decode_expr_with_depth(
bytes : Bytes,
i : Int,
depth : Int,
) -> Result[(Expr, Int), BinaryDecodeError] {
if depth > MAX_INSTRUCTION_NESTING_DEPTH {
return Err(BinaryDecodeError::InstructionNestingLimitExceeded)
}
let a = Array::new()
let mut i = i
while true {
match decode_instruction_with_depth(bytes, i, depth + 1) {
Ok((inst, next)) => {
a.push(inst)
i = next
}
Err(_) if bytes.get(i) == Some(0x0B) => break
Err(t) => return Err(t)
}
}
Ok((Expr::new(a), i + 1))
}
///|
pub impl Decode for Expr with fn decode(bytes, i) {
decode_expr_with_depth(bytes, i, 0)
}
///|
pub impl Decode for Table with fn decode(bytes, i) {
match (bytes.get(i), bytes.get(i + 1)) {
(Some(0x40), Some(0x00)) =>
match Decode::decode(bytes, i + 2) {
Ok((tt, i)) =>
match Decode::decode(bytes, i) {
Ok((e, i)) => Ok((Table::new(tt, Some(e)), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
_ =>
match Decode::decode(bytes, i) {
Ok((tt, i)) => Ok((Table::new(tt, None), i))
Err(t) => Err(t)
}
}
}
///|
pub impl Decode for Global with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Ok((gt, i)) =>
match Decode::decode(bytes, i) {
Ok((expr, i)) => Ok((Global::new(gt, expr), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
}
///|
pub impl Decode for ExternIdx with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x00) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((ExternIdx::func(idx), i))
Err(t) => Err(t)
}
Some(0x01) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((ExternIdx::table(idx), i))
Err(t) => Err(t)
}
Some(0x02) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((ExternIdx::mem(idx), i))
Err(t) => Err(t)
}
Some(0x03) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((ExternIdx::global(idx), i))
Err(t) => Err(t)
}
Some(0x04) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((ExternIdx::tag(idx), i))
Err(t) => Err(t)
}
Some(_) => Err(BinaryDecodeError::InvalidExternIndex)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
pub impl Decode for Export with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Ok((n, i)) =>
match Decode::decode(bytes, i) {
Ok((idx, i)) => Ok((Export::new(n, idx), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
}
///|
pub impl Decode for TableSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 4) {
Ok((content, next)) => Ok((TableSec::new(content), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for MemSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 5) {
Ok((content, next)) => Ok((MemSec::new(content), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for TagSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 13) {
Ok((content, next)) => Ok((TagSec::new(content), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for GlobalSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 6) {
Ok((content, next)) => Ok((GlobalSec::new(content), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for ExportSec with fn decode(bytes, i) {
match decode_section_vector_payload(bytes, i, 7) {
Ok((content, next)) => Ok((ExportSec::new(content), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for StartSec with fn decode(bytes, i) {
match
(
decode_section_payload(bytes, i, 8) :
Result[(FuncIdx, Int), BinaryDecodeError]) {
Ok((idx, next)) => Ok((StartSec::new(idx), next))
Err(t) => Err(t)
}
}
///|
pub impl Decode for Bytes with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Err(t) => Err(t)
Ok((@lib.U32(len), i)) if len <= (bytes.length() - i).reinterpret_as_uint() => {
let next = i + len.reinterpret_as_int()
let val = bytes[i:next].to_owned()
Ok((val, next))
}
Ok(_) => Err(BinaryDecodeError::InvalidOffset)
}
}
///|
pub impl Decode for ResumeHandler with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x00) =>
match Decode::decode(bytes, i + 1) {
Ok((tag, i)) =>
match Decode::decode(bytes, i) {
Ok((label, i)) => Ok((ResumeHandler::on_label(tag, label), i))
Err(err) => Err(err)
}
Err(err) => Err(err)
}
Some(0x01) =>
match Decode::decode(bytes, i + 1) {
Ok((tag, i)) => Ok((ResumeHandler::on_switch(tag), i))
Err(err) => Err(err)
}
Some(_) => Err(BinaryDecodeError::InvalidInstruction)
None => Err(BinaryDecodeError::IndexOutOfBounds)
}
}
///|
pub impl Decode for Catch with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x00) =>
match Decode::decode(bytes, i + 1) {
Ok((tidx, i)) =>
match Decode::decode(bytes, i) {
Ok((lidx, i)) => Ok((Catch::new(tidx, lidx), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0x01) =>
match Decode::decode(bytes, i + 1) {
Ok((tidx, i)) =>
match Decode::decode(bytes, i) {
Ok((lidx, i)) => Ok((Catch::ref_(tidx, lidx), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0x02) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Catch::all(idx), i))
Err(t) => Err(t)
}
Some(0x03) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Catch::all_ref(idx), i))
Err(t) => Err(t)
}
_ => Err(BinaryDecodeError::InvalidCatch)
}
}
///|
pub impl Decode for CastOp with fn decode(bytes, i) {
match bytes.get(i) {
Some(0x00) => Ok((CastOp::new(false, false), i + 1))
Some(0x01) => Ok((CastOp::new(true, false), i + 1))
Some(0x02) => Ok((CastOp::new(false, true), i + 1))
Some(0x03) => Ok((CastOp::new(true, true), i + 1))
_ => Err(BinaryDecodeError::InvalidCastOp)
}
}
///|
pub impl Decode for MemArg with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Ok((@lib.U32(n), i)) if n >= 64 && n <= 72 =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((@lib.U64(m), i)) => Ok((MemArg::new(n - 64, Some(x), m), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(n), i)) if n <= 8 =>
match Decode::decode(bytes, i) {
Ok((@lib.U64(m), i)) => Ok((MemArg::new(n, None, m), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
_ => Err(BinaryDecodeError::InvalidMemArg)
}
}
///|
fn decode_atomic_memarg(
bytes : Bytes,
i : Int,
is_rmw : Bool,
) -> Result[(@lib.AtomicOrder, MemArg, Int), BinaryDecodeError] {
let (@lib.U32(raw), decoded_next) = match Decode::decode(bytes, i) {
Ok(decoded) => decoded
Err(err) => return Err(err)
}
if (raw & 0xffffff80U) != 0U {
return Err(BinaryDecodeError::InvalidMemArg)
}
let mut next = decoded_next
let has_order = (raw & 0x10U) != 0U
let has_backing_array = (raw & 0x20U) != 0U
let has_memory_index = (raw & 0x40U) != 0U
if has_backing_array {
return Err(BinaryDecodeError::InvalidMemArg)
}
let align = raw & 0x0fU
if align > 8U {
return Err(BinaryDecodeError::InvalidMemArg)
}
let memory = if has_memory_index {
match Decode::decode(bytes, next) {
Ok((memory, after_memory)) => {
next = after_memory
Some(memory)
}
Err(err) => return Err(err)
}
} else {
None
}
let order = if has_order {
let decoded = if is_rmw {
decode_aggregate_atomic_rmw_order(bytes, next)
} else {
Decode::decode(bytes, next)
}
match decoded {
Ok((order, after_order)) => {
next = after_order
order
}
Err(err) => return Err(err)
}
} else {
@lib.AtomicOrder::seq_cst()
}
match Decode::decode(bytes, next) {
Ok((@lib.U64(offset), after_offset)) =>
Ok((order, MemArg::new(align, memory, offset), after_offset))
Err(err) => Err(err)
}
}
///|
fn decode_i8x16_shuffle_lanes(
bytes : Bytes,
i : Int,
) -> Result[(FixedArray[LaneIdx], Int), BinaryDecodeError] {
let lanes : FixedArray[LaneIdx] = FixedArray::make(16, LaneIdx::new(0))
let mut next = i
for lane_i in 0..<16 {
match bytes.get(next) {
Some(n) if n < 32 => {
lanes[lane_i] = LaneIdx::new(n)
next += 1
}
_ => return Err(BinaryDecodeError::InvalidLaneIndex)
}
}
Ok((lanes, next))
}
///|
fn i8x16_shuffle_from_lanes(lanes : FixedArray[LaneIdx]) -> Instruction {
Instruction::i8x16_shuffle(
lanes[0],
lanes[1],
lanes[2],
lanes[3],
lanes[4],
lanes[5],
lanes[6],
lanes[7],
lanes[8],
lanes[9],
lanes[10],
lanes[11],
lanes[12],
lanes[13],
lanes[14],
lanes[15],
)
}
///|
priv enum LegacyCatchDecodeFrame {
LegacyTaggedCatchFrame(TagIdx, Array[Instruction])
LegacyCatchAllFrame(Array[Instruction])
}
///|
priv enum StructuredDecodeFrame {
BlockFrame(BlockType, Int, Array[Instruction])
LoopFrame(BlockType, Int, Array[Instruction])
IfFrame(BlockType, Int, Array[Instruction], Array[Instruction]?)
LegacyTryFrame(
BlockType,
Int,
Array[Instruction],
Array[@lib.LegacyCatch],
LegacyCatchDecodeFrame?,
LabelIdx?
)
TryTableFrame(BlockType, Array[Catch], Int, Array[Instruction])
}
///|
fn structured_frame_body_instruction_depth(
frame : StructuredDecodeFrame,
) -> Int {
match frame {
BlockFrame(_, body_depth, _) => body_depth
LoopFrame(_, body_depth, _) => body_depth
IfFrame(_, body_depth, _, _) => body_depth
LegacyTryFrame(_, body_depth, _, _, _, _) => body_depth
TryTableFrame(_, _, body_depth, _) => body_depth
}
}
///|
fn structured_frame_push_instruction(
frame : StructuredDecodeFrame,
inst : Instruction,
) -> StructuredDecodeFrame {
// Only the already-owned active body changes. Every frame field and active
// catch stays the same, so keep the frame after appending instead of boxing
// another frame (and another catch wrapper) for each decoded instruction.
match frame {
BlockFrame(_, _, body)
| LoopFrame(_, _, body)
| TryTableFrame(_, _, _, body) => body.push(inst)
IfFrame(_, _, then_body, else_body) =>
match else_body {
Some(body) => body.push(inst)
None => then_body.push(inst)
}
LegacyTryFrame(_, _, body, _, active_catch, _) =>
match active_catch {
Some(LegacyTaggedCatchFrame(_, catch_body))
| Some(LegacyCatchAllFrame(catch_body)) => catch_body.push(inst)
None => body.push(inst)
}
}
frame
}
///|
fn structured_frame_finish(frame : StructuredDecodeFrame) -> Instruction {
match frame {
BlockFrame(bt, _, body) => Instruction::block(bt, Expr::new(body))
LoopFrame(bt, _, body) => Instruction::loop_(bt, Expr::new(body))
IfFrame(bt, _, then_body, else_body) =>
match else_body {
Some(else_body) => Instruction::if_(bt, then_body, Some(else_body))
None => Instruction::if_(bt, then_body, None)
}
LegacyTryFrame(bt, _, body, catches, active_catch, delegate) => {
match active_catch {
Some(LegacyTaggedCatchFrame(tag, catch_body)) =>
catches.push(@lib.LegacyCatch::tagged(tag, Expr::new(catch_body)))
Some(LegacyCatchAllFrame(catch_body)) =>
catches.push(@lib.LegacyCatch::all(Expr::new(catch_body)))
None => ()
}
Instruction::try_(bt, Expr::new(body), catches, delegate~)
}
TryTableFrame(bt, catches, _, body) =>
Instruction::try_table(bt, catches, Expr::new(body))
}
}
///|
fn decode_structured_frame_header(
bytes : Bytes,
i : Int,
depth : Int,
) -> Result[(StructuredDecodeFrame, Int), BinaryDecodeError] {
if depth + 1 > MAX_INSTRUCTION_NESTING_DEPTH {
return Err(BinaryDecodeError::InstructionNestingLimitExceeded)
}
let body_depth = depth + 2
match bytes.get(i) {
Some(0x02) =>
match Decode::decode(bytes, i + 1) {
Ok((bt, next)) => Ok((BlockFrame(bt, body_depth, []), next))
Err(err) => Err(err)
}
Some(0x03) =>
match Decode::decode(bytes, i + 1) {
Ok((bt, next)) => Ok((LoopFrame(bt, body_depth, []), next))
Err(err) => Err(err)
}
Some(0x04) =>
match Decode::decode(bytes, i + 1) {
Ok((bt, next)) => Ok((IfFrame(bt, body_depth, [], None), next))
Err(err) => Err(err)
}
Some(0x06) =>
match Decode::decode(bytes, i + 1) {
Ok((bt, next)) =>
Ok((LegacyTryFrame(bt, body_depth, [], [], None, None), next))
Err(err) => Err(err)
}
Some(0x1F) =>
match Decode::decode(bytes, i + 1) {
Ok((bt, next)) =>
match Decode::decode(bytes, next) {
Ok((catches, next)) =>
Ok((TryTableFrame(bt, catches, body_depth, []), next))
Err(err) => Err(err)
}
Err(err) => Err(err)
}
_ => Err(BinaryDecodeError::InvalidInstruction)
}
}
///|
fn decode_structured_instruction_with_depth(
bytes : Bytes,
i : Int,
depth : Int,
) -> Result[(Instruction, Int), BinaryDecodeError] {
let (initial_frame, next) = match
decode_structured_frame_header(bytes, i, depth) {
Ok(decoded) => decoded
Err(err) => return Err(err)
}
let frames : Array[StructuredDecodeFrame] = [initial_frame]
let mut pos = next
while frames.length() > 0 {
let frame = frames.pop().unwrap()
match (frame, bytes.get(pos)) {
(IfFrame(bt, body_depth, then_body, None), Some(0x05)) => {
pos += 1
frames.push(IfFrame(bt, body_depth, then_body, Some([])))
}
(
LegacyTryFrame(bt, body_depth, body, catches, active_catch, None),
Some(0x07),
) => {
match active_catch {
Some(LegacyTaggedCatchFrame(tag, catch_body)) =>
catches.push(@lib.LegacyCatch::tagged(tag, Expr::new(catch_body)))
Some(LegacyCatchAllFrame(_)) =>
return Err(BinaryDecodeError::InvalidInstruction)
None => ()
}
match Decode::decode(bytes, pos + 1) {
Ok((tag, next)) => {
frames.push(
LegacyTryFrame(
bt,
body_depth,
body,
catches,
Some(LegacyTaggedCatchFrame(tag, [])),
None,
),
)
pos = next
}
Err(err) => return Err(err)
}
}
(
LegacyTryFrame(bt, body_depth, body, catches, active_catch, None),
Some(0x19),
) => {
match active_catch {
Some(LegacyTaggedCatchFrame(tag, catch_body)) =>
catches.push(@lib.LegacyCatch::tagged(tag, Expr::new(catch_body)))
Some(LegacyCatchAllFrame(_)) =>
return Err(BinaryDecodeError::InvalidInstruction)
None => ()
}
frames.push(
LegacyTryFrame(
bt,
body_depth,
body,
catches,
Some(LegacyCatchAllFrame([])),
None,
),
)
pos += 1
}
(LegacyTryFrame(bt, _, body, catches, None, None), Some(0x18)) => {
if catches.length() > 0 {
return Err(BinaryDecodeError::InvalidInstruction)
}
let (delegate, next) = match Decode::decode(bytes, pos + 1) {
Ok(decoded) => decoded
Err(err) => return Err(err)
}
let inst = Instruction::try_(
bt,
Expr::new(body),
[],
delegate=Some(delegate),
)
pos = next
if frames.is_empty() {
return Ok((inst, pos))
}
let parent = frames.pop().unwrap()
frames.push(structured_frame_push_instruction(parent, inst))
}
(frame, Some(0x0B)) => {
let inst = structured_frame_finish(frame)
pos += 1
if frames.is_empty() {
return Ok((inst, pos))
}
let parent = frames.pop().unwrap()
frames.push(structured_frame_push_instruction(parent, inst))
}
(frame, Some(0x02))
| (frame, Some(0x03))
| (frame, Some(0x04))
| (frame, Some(0x06))
| (frame, Some(0x1F)) => {
let body_depth = structured_frame_body_instruction_depth(frame)
frames.push(frame)
match decode_structured_frame_header(bytes, pos, body_depth) {
Ok((child, next)) => {
frames.push(child)
pos = next
}
Err(err) => return Err(err)
}
}
(frame, _) => {
let body_depth = structured_frame_body_instruction_depth(frame)
match decode_instruction_with_depth(bytes, pos, body_depth) {
Ok((inst, next)) => {
frames.push(structured_frame_push_instruction(frame, inst))
pos = next
}
Err(err) => return Err(err)
}
}
}
}
Err(BinaryDecodeError::UnreachableDecodeState)
}
///|
fn decode_instruction_with_depth(
bytes : Bytes,
i : Int,
depth : Int,
) -> Result[(Instruction, Int), BinaryDecodeError] {
if depth > MAX_INSTRUCTION_NESTING_DEPTH {
return Err(BinaryDecodeError::InstructionNestingLimitExceeded)
}
match bytes.get(i) {
Some(0x00) => Ok((Instruction::unreachable_(), i + 1))
Some(0x01) => Ok((Instruction::nop(), i + 1))
Some(0x1A) => Ok((Instruction::drop(), i + 1))
Some(0x1B) => Ok((Instruction::select(types=None), i + 1))
Some(0x1C) =>
match Decode::decode(bytes, i + 1) {
Ok((vts, i)) => Ok((Instruction::select(types=Some(vts)), i))
Err(t) => Err(t)
}
Some(0x02) | Some(0x03) | Some(0x04) | Some(0x06) | Some(0x1F) =>
decode_structured_instruction_with_depth(bytes, i, depth)
Some(0x08) =>
match Decode::decode(bytes, i + 1) {
Ok((tag, i)) => Ok((Instruction::throw_(tag), i))
Err(t) => Err(t)
}
Some(0x09) =>
match Decode::decode(bytes, i + 1) {
Ok((depth, i)) => Ok((Instruction::rethrow(depth), i))
Err(t) => Err(t)
}
Some(0x0A) => Ok((Instruction::throw_ref(), i + 1))
Some(0x0C) =>
match Decode::decode(bytes, i + 1) {
Ok((lbl, i)) => Ok((Instruction::br(lbl), i))
Err(t) => Err(t)
}
Some(0x0D) =>
match Decode::decode(bytes, i + 1) {
Ok((lbl, i)) => Ok((Instruction::br_if(lbl), i))
Err(t) => Err(t)
}
Some(0x0E) =>
match Decode::decode(bytes, i + 1) {
Ok((lbls, i)) =>
match Decode::decode(bytes, i) {
Ok((lbl, i)) => Ok((Instruction::br_table(lbls, lbl), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0x0F) => Ok((Instruction::return_(), i + 1))
Some(0x10) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::call(idx), i))
Err(t) => Err(t)
}
Some(0x11) =>
match Decode::decode(bytes, i + 1) {
Ok((tidx, i)) =>
match Decode::decode(bytes, i) {
Ok((tblidx, i)) => Ok((Instruction::call_indirect(tidx, tblidx), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0x12) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::return_call(idx), i))
Err(t) => Err(t)
}
Some(0x13) =>
match Decode::decode(bytes, i + 1) {
Ok((tidx, i)) =>
match Decode::decode(bytes, i) {
Ok((tblidx, i)) =>
Ok((Instruction::return_call_indirect(tidx, tblidx), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0x14) =>
match Decode::decode(bytes, i + 1) {
Ok((tidx, i)) => Ok((Instruction::call_ref(tidx), i))
Err(t) => Err(t)
}
Some(0x15) =>
match Decode::decode(bytes, i + 1) {
Ok((tidx, i)) => Ok((Instruction::return_call_ref(tidx), i))
Err(t) => Err(t)
}
Some(0xE0) =>
match Decode::decode(bytes, i + 1) {
Ok((type_idx, i)) => Ok((Instruction::cont_new(type_idx), i))
Err(t) => Err(t)
}
Some(0xE1) =>
match Decode::decode(bytes, i + 1) {
Ok((source_type, i)) =>
match Decode::decode(bytes, i) {
Ok((target_type, i)) =>
Ok((Instruction::cont_bind(source_type, target_type), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0xE2) =>
match Decode::decode(bytes, i + 1) {
Ok((tag, i)) => Ok((Instruction::suspend(tag), i))
Err(t) => Err(t)
}
Some(0xE3) =>
match Decode::decode(bytes, i + 1) {
Ok((type_idx, i)) =>
match Decode::decode(bytes, i) {
Ok((handlers, i)) =>
Ok((Instruction::resume_(type_idx, handlers), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0xE4) =>
match Decode::decode(bytes, i + 1) {
Ok((type_idx, i)) =>
match Decode::decode(bytes, i) {
Ok((tag, i)) =>
match Decode::decode(bytes, i) {
Ok((handlers, i)) =>
Ok((Instruction::resume_throw(type_idx, tag, handlers), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0xE5) =>
match Decode::decode(bytes, i + 1) {
Ok((type_idx, i)) =>
match Decode::decode(bytes, i) {
Ok((handlers, i)) =>
Ok((Instruction::resume_throw_ref(type_idx, handlers), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0xE6) =>
match Decode::decode(bytes, i + 1) {
Ok((type_idx, i)) =>
match Decode::decode(bytes, i) {
Ok((tag, i)) => Ok((Instruction::stack_switch(type_idx, tag), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Some(0xD5) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::br_on_null(idx), i))
Err(t) => Err(t)
}
Some(0xD6) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::br_on_non_null(idx), i))
Err(t) => Err(t)
}
Some(0x20) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::local_get(idx), i))
Err(t) => Err(t)
}
Some(0x21) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::local_set(idx), i))
Err(t) => Err(t)
}
Some(0x22) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::local_tee(idx), i))
Err(t) => Err(t)
}
Some(0x23) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::global_get(idx), i))
Err(t) => Err(t)
}
Some(0x24) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::global_set(idx), i))
Err(t) => Err(t)
}
Some(0x25) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::table_get(idx), i))
Err(t) => Err(t)
}
Some(0x26) =>
match Decode::decode(bytes, i + 1) {
Ok((idx, i)) => Ok((Instruction::table_set(idx), i))
Err(t) => Err(t)
}
Some(0x28) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i32_load(), fn(ma) {
Instruction::i32_load(ma)
})
Some(0x29) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i64_load(), fn(ma) {
Instruction::i64_load(ma)
})
Some(0x2A) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::f32_load(), fn(ma) {
Instruction::f32_load(ma)
})
Some(0x2B) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::f64_load(), fn(ma) {
Instruction::f64_load(ma)
})
Some(0x2C) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i32_load8s(), fn(ma) {
Instruction::i32_load8s(ma)
})
Some(0x2D) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i32_load8u(), fn(ma) {
Instruction::i32_load8u(ma)
})
Some(0x2E) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i32_load16s(), fn(ma) {
Instruction::i32_load16s(ma)
})
Some(0x2F) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i32_load16u(), fn(ma) {
Instruction::i32_load16u(ma)
})
Some(0x30) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i64_load8s(), fn(ma) {
Instruction::i64_load8s(ma)
})
Some(0x31) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i64_load8u(), fn(ma) {
Instruction::i64_load8u(ma)
})
Some(0x32) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i64_load16s(), fn(ma) {
Instruction::i64_load16s(ma)
})
Some(0x33) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i64_load16u(), fn(ma) {
Instruction::i64_load16u(ma)
})
Some(0x34) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i64_load32s(), fn(ma) {
Instruction::i64_load32s(ma)
})
Some(0x35) =>
decode_memory_load(bytes, i + 1, @lib.LoadOp::i64_load32u(), fn(ma) {
Instruction::i64_load32u(ma)
})
Some(0x36) =>
decode_memory_store(bytes, i + 1, @lib.StoreOp::i32_store(), fn(ma) {
Instruction::i32_store(ma)
})
Some(0x37) =>
decode_memory_store(bytes, i + 1, @lib.StoreOp::i64_store(), fn(ma) {
Instruction::i64_store(ma)
})
Some(0x38) =>
decode_memory_store(bytes, i + 1, @lib.StoreOp::f32_store(), fn(ma) {
Instruction::f32_store(ma)
})
Some(0x39) =>
decode_memory_store(bytes, i + 1, @lib.StoreOp::f64_store(), fn(ma) {
Instruction::f64_store(ma)
})
Some(0x3A) =>
decode_memory_store(bytes, i + 1, @lib.StoreOp::i32_store8(), fn(ma) {
Instruction::i32_store8(ma)
})
Some(0x3B) =>
decode_memory_store(bytes, i + 1, @lib.StoreOp::i32_store16(), fn(ma) {
Instruction::i32_store16(ma)
})
Some(0x3C) =>
decode_memory_store(bytes, i + 1, @lib.StoreOp::i64_store8(), fn(ma) {
Instruction::i64_store8(ma)
})
Some(0x3D) =>
decode_memory_store(bytes, i + 1, @lib.StoreOp::i64_store16(), fn(ma) {
Instruction::i64_store16(ma)
})
Some(0x3E) =>
decode_memory_store(bytes, i + 1, @lib.StoreOp::i64_store32(), fn(ma) {
Instruction::i64_store32(ma)
})
Some(0x3F) =>
match Decode::decode(bytes, i + 1) {
Ok((x, i)) => Ok((Instruction::memory_size(x), i))
Err(t) => Err(t)
}
Some(0x40) =>
match Decode::decode(bytes, i + 1) {
Ok((x, i)) => Ok((Instruction::memory_grow(x), i))
Err(t) => Err(t)
}
Some(0xD0) =>
match decode_ref_heap_type(bytes, i + 1) {
Ok((exact, ht, i)) =>
Ok((Instruction::ref_null_type(RefType::new(true, ht, exact~)), i))
Err(t) =>
match Decode::decode(bytes, i + 1) {
Ok((abs, i)) => Ok((Instruction::ref_null(HeapType::abs(abs)), i))
Err(_) => Err(t)
}
}
Some(0xD1) => Ok((Instruction::ref_is_null(), i + 1))
Some(0xD2) =>
match Decode::decode(bytes, i + 1) {
Ok((x, i)) => Ok((Instruction::ref_func(x), i))
Err(t) => Err(t)
}
Some(0xD3) => Ok((Instruction::ref_eq(), i + 1))
Some(0xD4) => Ok((Instruction::ref_as_non_null(), i + 1))
Some(0x45) => Ok((Instruction::i32_eqz(), i + 1))
Some(0x46) => Ok((Instruction::i32_eq(), i + 1))
Some(0x47) => Ok((Instruction::i32_ne(), i + 1))
Some(0x48) => Ok((Instruction::i32_lt_s(), i + 1))
Some(0x49) => Ok((Instruction::i32_lt_u(), i + 1))
Some(0x4A) => Ok((Instruction::i32_gt_s(), i + 1))
Some(0x4B) => Ok((Instruction::i32_gt_u(), i + 1))
Some(0x4C) => Ok((Instruction::i32_le_s(), i + 1))
Some(0x4D) => Ok((Instruction::i32_le_u(), i + 1))
Some(0x4E) => Ok((Instruction::i32_ge_s(), i + 1))
Some(0x4F) => Ok((Instruction::i32_ge_u(), i + 1))
Some(0x50) => Ok((Instruction::i64_eqz(), i + 1))
Some(0x51) => Ok((Instruction::i64_eq(), i + 1))
Some(0x52) => Ok((Instruction::i64_ne(), i + 1))
Some(0x53) => Ok((Instruction::i64_lt_s(), i + 1))
Some(0x54) => Ok((Instruction::i64_lt_u(), i + 1))
Some(0x55) => Ok((Instruction::i64_gt_s(), i + 1))
Some(0x56) => Ok((Instruction::i64_gt_u(), i + 1))
Some(0x57) => Ok((Instruction::i64_le_s(), i + 1))
Some(0x58) => Ok((Instruction::i64_le_u(), i + 1))
Some(0x59) => Ok((Instruction::i64_ge_s(), i + 1))
Some(0x5A) => Ok((Instruction::i64_ge_u(), i + 1))
Some(0x5B) => Ok((Instruction::f32_eq(), i + 1))
Some(0x5C) => Ok((Instruction::f32_ne(), i + 1))
Some(0x5D) => Ok((Instruction::f32_lt(), i + 1))
Some(0x5E) => Ok((Instruction::f32_gt(), i + 1))
Some(0x5F) => Ok((Instruction::f32_le(), i + 1))
Some(0x60) => Ok((Instruction::f32_ge(), i + 1))
Some(0x61) => Ok((Instruction::f64_eq(), i + 1))
Some(0x62) => Ok((Instruction::f64_ne(), i + 1))
Some(0x63) => Ok((Instruction::f64_lt(), i + 1))
Some(0x64) => Ok((Instruction::f64_gt(), i + 1))
Some(0x65) => Ok((Instruction::f64_le(), i + 1))
Some(0x66) => Ok((Instruction::f64_ge(), i + 1))
Some(0x67) => Ok((Instruction::i32_clz(), i + 1))
Some(0x68) => Ok((Instruction::i32_ctz(), i + 1))
Some(0x69) => Ok((Instruction::i32_popcnt(), i + 1))
Some(0x6A) => Ok((Instruction::i32_add(), i + 1))
Some(0x6B) => Ok((Instruction::i32_sub(), i + 1))
Some(0x6C) => Ok((Instruction::i32_mul(), i + 1))
Some(0x6D) => Ok((Instruction::i32_div_s(), i + 1))
Some(0x6E) => Ok((Instruction::i32_div_u(), i + 1))
Some(0x6F) => Ok((Instruction::i32_rem_s(), i + 1))
Some(0x70) => Ok((Instruction::i32_rem_u(), i + 1))
Some(0x71) => Ok((Instruction::i32_and(), i + 1))
Some(0x72) => Ok((Instruction::i32_or(), i + 1))
Some(0x73) => Ok((Instruction::i32_xor(), i + 1))
Some(0x74) => Ok((Instruction::i32_shl(), i + 1))
Some(0x75) => Ok((Instruction::i32_shr_s(), i + 1))
Some(0x76) => Ok((Instruction::i32_shr_u(), i + 1))
Some(0x77) => Ok((Instruction::i32_rotl(), i + 1))
Some(0x78) => Ok((Instruction::i32_rotr(), i + 1))
Some(0x79) => Ok((Instruction::i64_clz(), i + 1))
Some(0x7A) => Ok((Instruction::i64_ctz(), i + 1))
Some(0x7B) => Ok((Instruction::i64_popcnt(), i + 1))
Some(0x7C) => Ok((Instruction::i64_add(), i + 1))
Some(0x7D) => Ok((Instruction::i64_sub(), i + 1))
Some(0x7E) => Ok((Instruction::i64_mul(), i + 1))
Some(0x7F) => Ok((Instruction::i64_div_s(), i + 1))
Some(0x80) => Ok((Instruction::i64_div_u(), i + 1))
Some(0x81) => Ok((Instruction::i64_rem_s(), i + 1))
Some(0x82) => Ok((Instruction::i64_rem_u(), i + 1))
Some(0x83) => Ok((Instruction::i64_and(), i + 1))
Some(0x84) => Ok((Instruction::i64_or(), i + 1))
Some(0x85) => Ok((Instruction::i64_xor(), i + 1))
Some(0x86) => Ok((Instruction::i64_shl(), i + 1))
Some(0x87) => Ok((Instruction::i64_shr_s(), i + 1))
Some(0x88) => Ok((Instruction::i64_shr_u(), i + 1))
Some(0x89) => Ok((Instruction::i64_rotl(), i + 1))
Some(0x8A) => Ok((Instruction::i64_rotr(), i + 1))
Some(0x8B) => Ok((Instruction::f32_abs(), i + 1))
Some(0x8C) => Ok((Instruction::f32_neg(), i + 1))
Some(0x8D) => Ok((Instruction::f32_ceil(), i + 1))
Some(0x8E) => Ok((Instruction::f32_floor(), i + 1))
Some(0x8F) => Ok((Instruction::f32_trunc(), i + 1))
Some(0x90) => Ok((Instruction::f32_nearest(), i + 1))
Some(0x91) => Ok((Instruction::f32_sqrt(), i + 1))
Some(0x92) => Ok((Instruction::f32_add(), i + 1))
Some(0x93) => Ok((Instruction::f32_sub(), i + 1))
Some(0x94) => Ok((Instruction::f32_mul(), i + 1))
Some(0x95) => Ok((Instruction::f32_div(), i + 1))
Some(0x96) => Ok((Instruction::f32_min(), i + 1))
Some(0x97) => Ok((Instruction::f32_max(), i + 1))
Some(0x98) => Ok((Instruction::f32_copysign(), i + 1))
Some(0x99) => Ok((Instruction::f64_abs(), i + 1))
Some(0x9A) => Ok((Instruction::f64_neg(), i + 1))
Some(0x9B) => Ok((Instruction::f64_ceil(), i + 1))
Some(0x9C) => Ok((Instruction::f64_floor(), i + 1))
Some(0x9D) => Ok((Instruction::f64_trunc(), i + 1))
Some(0x9E) => Ok((Instruction::f64_nearest(), i + 1))
Some(0x9F) => Ok((Instruction::f64_sqrt(), i + 1))
Some(0xA0) => Ok((Instruction::f64_add(), i + 1))
Some(0xA1) => Ok((Instruction::f64_sub(), i + 1))
Some(0xA2) => Ok((Instruction::f64_mul(), i + 1))
Some(0xA3) => Ok((Instruction::f64_div(), i + 1))
Some(0xA4) => Ok((Instruction::f64_min(), i + 1))
Some(0xA5) => Ok((Instruction::f64_max(), i + 1))
Some(0xA6) => Ok((Instruction::f64_copysign(), i + 1))
Some(0xA7) => Ok((Instruction::i32_wrap_i64(), i + 1))
Some(0xA8) => Ok((Instruction::i32_trunc_f32s(), i + 1))
Some(0xA9) => Ok((Instruction::i32_trunc_f32u(), i + 1))
Some(0xAA) => Ok((Instruction::i32_trunc_f64s(), i + 1))
Some(0xAB) => Ok((Instruction::i32_trunc_f64u(), i + 1))
Some(0xAC) => Ok((Instruction::i64_extend_i32s(), i + 1))
Some(0xAD) => Ok((Instruction::i64_extend_i32u(), i + 1))
Some(0xAE) => Ok((Instruction::i64_trunc_f32s(), i + 1))
Some(0xAF) => Ok((Instruction::i64_trunc_f32u(), i + 1))
Some(0xB0) => Ok((Instruction::i64_trunc_f64s(), i + 1))
Some(0xB1) => Ok((Instruction::i64_trunc_f64u(), i + 1))
Some(0xB2) => Ok((Instruction::f32_convert_i32s(), i + 1))
Some(0xB3) => Ok((Instruction::f32_convert_i32u(), i + 1))
Some(0xB4) => Ok((Instruction::f32_convert_i64s(), i + 1))
Some(0xB5) => Ok((Instruction::f32_convert_i64u(), i + 1))
Some(0xB6) => Ok((Instruction::f32_demote_f64(), i + 1))
Some(0xB7) => Ok((Instruction::f64_convert_i32s(), i + 1))
Some(0xB8) => Ok((Instruction::f64_convert_i32u(), i + 1))
Some(0xB9) => Ok((Instruction::f64_convert_i64s(), i + 1))
Some(0xBA) => Ok((Instruction::f64_convert_i64u(), i + 1))
Some(0xBB) => Ok((Instruction::f64_promote_f32(), i + 1))
Some(0xBC) => Ok((Instruction::i32_reinterpret_f32(), i + 1))
Some(0xBD) => Ok((Instruction::i64_reinterpret_f64(), i + 1))
Some(0xBE) => Ok((Instruction::f32_reinterpret_i32(), i + 1))
Some(0xBF) => Ok((Instruction::f64_reinterpret_i64(), i + 1))
Some(0xC0) => Ok((Instruction::i32_extend8s(), i + 1))
Some(0xC1) => Ok((Instruction::i32_extend16s(), i + 1))
Some(0xC2) => Ok((Instruction::i64_extend8s(), i + 1))
Some(0xC3) => Ok((Instruction::i64_extend16s(), i + 1))
Some(0xC4) => Ok((Instruction::i64_extend32s(), i + 1))
Some(0x41) =>
match Decode::decode(bytes, i + 1) {
Ok((n, i)) => Ok((Instruction::i32_const(n), i))
Err(t) => Err(t)
}
Some(0x42) =>
match Decode::decode(bytes, i + 1) {
Ok((n, i)) => Ok((Instruction::i64_const(n), i))
Err(t) => Err(t)
}
Some(0x43) =>
match Decode::decode(bytes, i + 1) {
Ok((n, i)) => Ok((Instruction::f32_const(n), i))
Err(t) => Err(t)
}
Some(0x44) =>
match Decode::decode(bytes, i + 1) {
Ok((n, i)) => Ok((Instruction::f64_const(n), i))
Err(t) => Err(t)
}
// Section: Control Flow/Aggregate 0xFB
Some(0xFB) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(0), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::struct_new(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(1), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::struct_new_default(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(32), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::struct_new_desc(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(33), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::struct_new_default_desc(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(2), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((n, i)) => Ok((Instruction::struct_get(x, n), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(3), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((n, i)) => Ok((Instruction::struct_get_s(x, n), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(4), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((n, i)) => Ok((Instruction::struct_get_u(x, n), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(5), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((n, i)) => Ok((Instruction::struct_set(x, n), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(6), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::array_new(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(7), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::array_new_default(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(8), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((n, i)) => Ok((Instruction::array_new_fixed(x, n), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(9), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((n, i)) => Ok((Instruction::array_new_data(x, n), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(10), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((n, i)) => Ok((Instruction::array_new_elem(x, n), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(11), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::array_get(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(12), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::array_get_s(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(13), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::array_get_u(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(14), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::array_set(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(15), i)) => Ok((Instruction::array_len(), i))
Ok((@lib.U32(16), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::array_fill(x), i))
Err(t) => Err(t)
}
Ok((@lib.U32(17), i)) =>
match Decode::decode(bytes, i) {
Ok((x1, i)) =>
match Decode::decode(bytes, i) {
Ok((x2, i)) => Ok((Instruction::array_copy(x1, x2), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(18), i)) =>
match Decode::decode(bytes, i) {
Ok((x1, i)) =>
match Decode::decode(bytes, i) {
Ok((x2, i)) => Ok((Instruction::array_init_data(x1, x2), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(19), i)) =>
match Decode::decode(bytes, i) {
Ok((x1, i)) =>
match Decode::decode(bytes, i) {
Ok((x2, i)) => Ok((Instruction::array_init_elem(x1, x2), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(0x82), i)) =>
match Decode::decode(bytes, i) {
Ok((idx, i)) =>
match decode_string_const_literal(idx) {
Ok(literal) => Ok((Instruction::string_const(literal), i))
Err(err) => Err(err)
}
Err(t) => Err(t)
}
Ok((@lib.U32(0x85), i)) => Ok((Instruction::string_measure_wtf16(), i))
Ok((@lib.U32(0x88), i)) => Ok((Instruction::string_concat(), i))
Ok((@lib.U32(0x89), i)) => Ok((Instruction::string_eq(), i))
Ok((@lib.U32(0x98), i)) => Ok((Instruction::string_as_wtf16(), i))
Ok((@lib.U32(0x9A), i)) =>
Ok((Instruction::stringview_wtf16_get_codeunit(), i))
Ok((@lib.U32(0x9C), i)) =>
Ok((Instruction::stringview_wtf16_slice(), i))
Ok((@lib.U32(0xB0), i)) => Ok((Instruction::string_new_utf8_array(), i))
Ok((@lib.U32(0xB1), i)) =>
Ok((Instruction::string_new_wtf16_array(), i))
Ok((@lib.U32(0xB2), i)) =>
Ok((Instruction::string_encode_utf8_array(), i))
Ok((@lib.U32(0xB3), i)) =>
Ok((Instruction::string_encode_wtf16_array(), i))
Ok((@lib.U32(0xB4), i)) =>
Ok((Instruction::string_new_lossy_utf8_array(), i))
Ok((@lib.U32(0xB5), i)) => Ok((Instruction::string_new_wtf8_array(), i))
Ok((@lib.U32(0xB6), i)) =>
Ok((Instruction::string_encode_lossy_utf8_array(), i))
Ok((@lib.U32(0xB7), i)) =>
Ok((Instruction::string_encode_wtf8_array(), i))
Ok((@lib.U32(20), i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((exact, ht, i)) =>
Ok(
(Instruction::ref_test_type(RefType::new(false, ht, exact~)), i),
)
Err(t) => Err(t)
}
Ok((@lib.U32(21), i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((exact, ht, i)) =>
Ok(
(Instruction::ref_test_type(RefType::new(true, ht, exact~)), i),
)
Err(t) => Err(t)
}
Ok((@lib.U32(22), i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((exact, ht, i)) =>
Ok(
(Instruction::ref_cast_type(RefType::new(false, ht, exact~)), i),
)
Err(t) => Err(t)
}
Ok((@lib.U32(23), i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((exact, ht, i)) =>
Ok(
(Instruction::ref_cast_type(RefType::new(true, ht, exact~)), i),
)
Err(t) => Err(t)
}
Ok((U32(24), i)) => {
let castop : Result[(CastOp, Int), BinaryDecodeError] = Decode::decode(
bytes, i,
)
match castop {
Ok((CastOp(source_nullable, target_nullable, _, _), i)) =>
match Decode::decode(bytes, i) {
Ok((label, i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((source_exact, source_heap, i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((target_exact, target_heap, i)) =>
Ok(
(
Instruction::br_on_cast(
label,
source_nullable,
source_heap,
target_nullable,
target_heap,
source_exact~,
target_exact~,
),
i,
),
)
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
}
Ok((U32(25), i)) => {
let castop : Result[(CastOp, Int), BinaryDecodeError] = Decode::decode(
bytes, i,
)
match castop {
Ok((CastOp(source_nullable, target_nullable, _, _), i)) =>
match Decode::decode(bytes, i) {
Ok((label, i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((source_exact, source_heap, i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((target_exact, target_heap, i)) =>
Ok(
(
Instruction::br_on_cast_fail(
label,
source_nullable,
source_heap,
target_nullable,
target_heap,
source_exact~,
target_exact~,
),
i,
),
)
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
}
Ok((@lib.U32(id), i)) if id == 37U || id == 38U => {
let castop : Result[(CastOp, Int), BinaryDecodeError] = Decode::decode(
bytes, i,
)
match castop {
Ok((CastOp(source_nullable, target_nullable, _, _), i)) =>
match Decode::decode(bytes, i) {
Ok((label, i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((source_exact, source_heap, i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((target_exact, target_heap, i)) => {
let source = RefType::new(
source_nullable,
source_heap,
exact=source_exact,
)
let target = RefType::new(
target_nullable,
target_heap,
exact=target_exact,
)
if id == 37U {
Ok(
(
Instruction::br_on_cast_desc_eq(
label, source, target,
),
i,
),
)
} else {
Ok(
(
Instruction::br_on_cast_desc_eq_fail(
label, source, target,
),
i,
),
)
}
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
}
Ok((U32(26), i)) => Ok((Instruction::any_convert_extern(), i))
Ok((U32(27), i)) => Ok((Instruction::extern_convert_any(), i))
Ok((U32(28), i)) => Ok((Instruction::ref_i31(), i))
Ok((U32(31), i)) => Ok((Instruction::ref_i31_shared(), i))
Ok((U32(29), i)) => Ok((Instruction::i31_get_s(), i))
Ok((U32(30), i)) => Ok((Instruction::i31_get_u(), i))
Ok((U32(34), i)) =>
match Decode::decode(bytes, i) {
Ok((ti, i)) => Ok((Instruction::ref_get_desc(ti), i))
Err(t) => Err(t)
}
Ok((@lib.U32(35), i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((exact, ht, i)) =>
Ok(
(
Instruction::ref_cast_desc_eq_type(
RefType::new(false, ht, exact~),
),
i,
),
)
Err(t) => Err(t)
}
Ok((@lib.U32(36), i)) =>
match decode_ref_heap_type(bytes, i) {
Ok((exact, ht, i)) =>
Ok(
(
Instruction::ref_cast_desc_eq_type(
RefType::new(true, ht, exact~),
),
i,
),
)
Err(t) => Err(t)
}
Err(t) => Err(t)
_ => Err(BinaryDecodeError::InvalidInstruction)
}
// Section: Memory/Table/Elem
Some(0xFC) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(0), i)) => Ok((Instruction::i32_trunc_sat_f32s(), i))
Ok((U32(1), i)) => Ok((Instruction::i32_trunc_sat_f32u(), i))
Ok((U32(2), i)) => Ok((Instruction::i32_trunc_sat_f64s(), i))
Ok((U32(3), i)) => Ok((Instruction::i32_trunc_sat_f64u(), i))
Ok((U32(4), i)) => Ok((Instruction::i64_trunc_sat_f32s(), i))
Ok((U32(5), i)) => Ok((Instruction::i64_trunc_sat_f32u(), i))
Ok((U32(6), i)) => Ok((Instruction::i64_trunc_sat_f64s(), i))
Ok((U32(7), i)) => Ok((Instruction::i64_trunc_sat_f64u(), i))
Ok((U32(8), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((y, i)) => Ok((Instruction::memory_init(x, y), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(9), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::data_drop(x), i))
Err(t) => Err(t)
}
Ok((U32(10), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((y, i)) => Ok((Instruction::memory_copy(x, y), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(11), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) => Ok((Instruction::memory_fill(x), i))
Err(t) => Err(t)
}
Ok((U32(12), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((y, i)) => Ok((Instruction::table_init(x, y), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(13), i)) =>
match Decode::decode(bytes, i) {
Ok((y, i)) => Ok((Instruction::elem_drop(y), i))
Err(t) => Err(t)
}
Ok((U32(14), i)) =>
match Decode::decode(bytes, i) {
Ok((x, i)) =>
match Decode::decode(bytes, i) {
Ok((y, i)) => Ok((Instruction::table_copy(x, y), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(15), i)) =>
match Decode::decode(bytes, i) {
Ok((y, i)) => Ok((Instruction::table_grow(y), i))
Err(t) => Err(t)
}
Ok((U32(16), i)) =>
match Decode::decode(bytes, i) {
Ok((y, i)) => Ok((Instruction::table_size(y), i))
Err(t) => Err(t)
}
Ok((U32(17), i)) =>
match Decode::decode(bytes, i) {
Ok((y, i)) => Ok((Instruction::table_fill(y), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
_ => Err(BinaryDecodeError::InvalidInstruction)
}
// Section: Threads atomics
Some(0xFE) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(0), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::memory_atomic_notify(m), i))
Err(t) => Err(t)
}
Ok((@lib.U32(1), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::memory_atomic_wait32(m), i))
Err(t) => Err(t)
}
Ok((@lib.U32(2), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::memory_atomic_wait64(m), i))
Err(t) => Err(t)
}
Ok((@lib.U32(3), i)) =>
match Decode::decode(bytes, i) {
Ok((order, i)) => Ok((Instruction::atomic_fence(order~), i))
Err(_) => Err(BinaryDecodeError::InvalidAtomicFenceImmediate)
}
Ok((@lib.U32(5), i)) =>
match Decode::decode(bytes, i) {
Ok((type_idx, i)) =>
match Decode::decode(bytes, i) {
Ok((field, i)) =>
Ok((Instruction::struct_wait(type_idx, field), i))
Err(err) => Err(err)
}
Err(err) => Err(err)
}
Ok((@lib.U32(6), i)) => Ok((Instruction::waitqueue_notify(), i))
Ok((@lib.U32(7), i)) => Ok((Instruction::waitqueue_new(), i))
Ok((@lib.U32(15), i)) => Ok((Instruction::publish(), i))
Ok((@lib.U32(16), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i32_atomic_load(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(17), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i64_atomic_load(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(18), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i32_atomic_load8_u(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(19), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i32_atomic_load16_u(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(20), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i64_atomic_load8_u(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(21), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i64_atomic_load16_u(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(22), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i64_atomic_load32_u(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(id), i)) if id >= 0x5C && id <= 0x5F =>
match Decode::decode(bytes, i) {
Ok((order, i)) =>
match Decode::decode(bytes, i) {
Ok((type_idx, i)) =>
match Decode::decode(bytes, i) {
Ok((field_idx, i)) => {
let instr = match id {
0x5C =>
Instruction::struct_atomic_get(
order, type_idx, field_idx,
)
0x5D =>
Instruction::struct_atomic_get_s(
order, type_idx, field_idx,
)
0x5F =>
Instruction::struct_atomic_set(
order, type_idx, field_idx,
)
_ =>
Instruction::struct_atomic_get_u(
order, type_idx, field_idx,
)
}
Ok((instr, i))
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(id), i)) if id >= 0x60 && id <= 0x66 =>
match decode_aggregate_atomic_rmw_order(bytes, i) {
Ok((order, i)) =>
match Decode::decode(bytes, i) {
Ok((type_idx, i)) =>
match Decode::decode(bytes, i) {
Ok((field_idx, i)) => {
let instr = match id {
0x60 =>
Instruction::struct_atomic_rmw(
@lib.AggregateAtomicRmwOp::add(),
type_idx,
field_idx,
order~,
)
0x61 =>
Instruction::struct_atomic_rmw(
@lib.AggregateAtomicRmwOp::sub(),
type_idx,
field_idx,
order~,
)
0x62 =>
Instruction::struct_atomic_rmw(
@lib.AggregateAtomicRmwOp::and_(),
type_idx,
field_idx,
order~,
)
0x63 =>
Instruction::struct_atomic_rmw(
@lib.AggregateAtomicRmwOp::or_(),
type_idx,
field_idx,
order~,
)
0x64 =>
Instruction::struct_atomic_rmw(
@lib.AggregateAtomicRmwOp::xor(),
type_idx,
field_idx,
order~,
)
0x65 =>
Instruction::struct_atomic_rmw(
@lib.AggregateAtomicRmwOp::xchg(),
type_idx,
field_idx,
order~,
)
_ =>
Instruction::struct_atomic_cmpxchg(
type_idx,
field_idx,
order~,
)
}
Ok((instr, i))
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(id), i)) if id >= 0x67 && id <= 0x6A =>
match Decode::decode(bytes, i) {
Ok((order, i)) =>
match Decode::decode(bytes, i) {
Ok((type_idx, i)) => {
let instr = match id {
0x67 => Instruction::array_atomic_get(order, type_idx)
0x68 => Instruction::array_atomic_get_s(order, type_idx)
0x6A => Instruction::array_atomic_set(order, type_idx)
_ => Instruction::array_atomic_get_u(order, type_idx)
}
Ok((instr, i))
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(id), i)) if id >= 0x6B && id <= 0x71 =>
match decode_aggregate_atomic_rmw_order(bytes, i) {
Ok((order, i)) =>
match Decode::decode(bytes, i) {
Ok((type_idx, i)) => {
let instr = match id {
0x6B =>
Instruction::array_atomic_rmw(
@lib.AggregateAtomicRmwOp::add(),
type_idx,
order~,
)
0x6C =>
Instruction::array_atomic_rmw(
@lib.AggregateAtomicRmwOp::sub(),
type_idx,
order~,
)
0x6D =>
Instruction::array_atomic_rmw(
@lib.AggregateAtomicRmwOp::and_(),
type_idx,
order~,
)
0x6E =>
Instruction::array_atomic_rmw(
@lib.AggregateAtomicRmwOp::or_(),
type_idx,
order~,
)
0x6F =>
Instruction::array_atomic_rmw(
@lib.AggregateAtomicRmwOp::xor(),
type_idx,
order~,
)
0x70 =>
Instruction::array_atomic_rmw(
@lib.AggregateAtomicRmwOp::xchg(),
type_idx,
order~,
)
_ => Instruction::array_atomic_cmpxchg(type_idx, order~)
}
Ok((instr, i))
}
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((@lib.U32(23), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i32_atomic_store(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(24), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i64_atomic_store(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(25), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i32_atomic_store8(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(26), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i32_atomic_store16(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(27), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i64_atomic_store8(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(28), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i64_atomic_store16(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(29), i)) =>
match decode_atomic_memarg(bytes, i, false) {
Ok((order, m, i)) =>
Ok((Instruction::i64_atomic_store32(m, order~), i))
Err(t) => Err(t)
}
Ok((@lib.U32(id), i)) if id >= 30 && id <= 71 =>
match decode_atomic_memarg(bytes, i, true) {
Ok((order, m, i)) => {
let op : AtomicRmwOp = match id {
30 => AtomicRmwOp::i32_add()
31 => AtomicRmwOp::i64_add()
32 => AtomicRmwOp::i32_8_add_u()
33 => AtomicRmwOp::i32_16_add_u()
34 => AtomicRmwOp::i64_8_add_u()
35 => AtomicRmwOp::i64_16_add_u()
36 => AtomicRmwOp::i64_32_add_u()
37 => AtomicRmwOp::i32_sub()
38 => AtomicRmwOp::i64_sub()
39 => AtomicRmwOp::i32_8_sub_u()
40 => AtomicRmwOp::i32_16_sub_u()
41 => AtomicRmwOp::i64_8_sub_u()
42 => AtomicRmwOp::i64_16_sub_u()
43 => AtomicRmwOp::i64_32_sub_u()
44 => AtomicRmwOp::i32_and()
45 => AtomicRmwOp::i64_and()
46 => AtomicRmwOp::i32_8_and_u()
47 => AtomicRmwOp::i32_16_and_u()
48 => AtomicRmwOp::i64_8_and_u()
49 => AtomicRmwOp::i64_16_and_u()
50 => AtomicRmwOp::i64_32_and_u()
51 => AtomicRmwOp::i32_or()
52 => AtomicRmwOp::i64_or()
53 => AtomicRmwOp::i32_8_or_u()
54 => AtomicRmwOp::i32_16_or_u()
55 => AtomicRmwOp::i64_8_or_u()
56 => AtomicRmwOp::i64_16_or_u()
57 => AtomicRmwOp::i64_32_or_u()
58 => AtomicRmwOp::i32_xor()
59 => AtomicRmwOp::i64_xor()
60 => AtomicRmwOp::i32_8_xor_u()
61 => AtomicRmwOp::i32_16_xor_u()
62 => AtomicRmwOp::i64_8_xor_u()
63 => AtomicRmwOp::i64_16_xor_u()
64 => AtomicRmwOp::i64_32_xor_u()
65 => AtomicRmwOp::i32_xchg()
66 => AtomicRmwOp::i64_xchg()
67 => AtomicRmwOp::i32_8_xchg_u()
68 => AtomicRmwOp::i32_16_xchg_u()
69 => AtomicRmwOp::i64_8_xchg_u()
70 => AtomicRmwOp::i64_16_xchg_u()
_ => AtomicRmwOp::i64_32_xchg_u()
}
Ok((Instruction::atomic_rmw(op, m, order~), i))
}
Err(t) => Err(t)
}
Ok((@lib.U32(id), i)) if id >= 72 && id <= 78 =>
match decode_atomic_memarg(bytes, i, true) {
Ok((order, m, i)) => {
let op : AtomicCmpxchgOp = match id {
72 => AtomicCmpxchgOp::i32()
73 => AtomicCmpxchgOp::i64()
74 => AtomicCmpxchgOp::i32_8_u()
75 => AtomicCmpxchgOp::i32_16_u()
76 => AtomicCmpxchgOp::i64_8_u()
77 => AtomicCmpxchgOp::i64_16_u()
_ => AtomicCmpxchgOp::i64_32_u()
}
Ok((Instruction::atomic_cmpxchg(op, m, order~), i))
}
Err(t) => Err(t)
}
Err(t) => Err(t)
_ => Err(BinaryDecodeError::InvalidAtomicInstruction)
}
// Section: Vector
Some(0xFD) =>
match Decode::decode(bytes, i + 1) {
Ok((@lib.U32(0), i)) =>
decode_memory_load(bytes, i, @lib.LoadOp::v128_load(), fn(ma) {
Instruction::v128_load(ma)
})
Ok((U32(1), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load8x8s(m), i))
Err(t) => Err(t)
}
Ok((U32(2), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load8x8u(m), i))
Err(t) => Err(t)
}
Ok((U32(3), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load16x4s(m), i))
Err(t) => Err(t)
}
Ok((U32(4), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load16x4u(m), i))
Err(t) => Err(t)
}
Ok((U32(5), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load32x2s(m), i))
Err(t) => Err(t)
}
Ok((U32(6), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load32x2u(m), i))
Err(t) => Err(t)
}
Ok((U32(7), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load8_splat(m), i))
Err(t) => Err(t)
}
Ok((U32(8), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load16_splat(m), i))
Err(t) => Err(t)
}
Ok((U32(9), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load32_splat(m), i))
Err(t) => Err(t)
}
Ok((U32(10), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load64_splat(m), i))
Err(t) => Err(t)
}
Ok((U32(11), i)) =>
decode_memory_store(bytes, i, @lib.StoreOp::v128_store(), fn(ma) {
Instruction::v128_store(ma)
})
Ok((U32(12), i)) =>
// 16 bytes const
if bytes.length() >= i + 16 {
Ok(
(
Instruction::v128_const(
bytes.unsafe_get(i),
bytes.unsafe_get(i + 1),
bytes.unsafe_get(i + 2),
bytes.unsafe_get(i + 3),
bytes.unsafe_get(i + 4),
bytes.unsafe_get(i + 5),
bytes.unsafe_get(i + 6),
bytes.unsafe_get(i + 7),
bytes.unsafe_get(i + 8),
bytes.unsafe_get(i + 9),
bytes.unsafe_get(i + 10),
bytes.unsafe_get(i + 11),
bytes.unsafe_get(i + 12),
bytes.unsafe_get(i + 13),
bytes.unsafe_get(i + 14),
bytes.unsafe_get(i + 15),
),
i + 16,
),
)
} else {
Err(BinaryDecodeError::InvalidInstruction)
}
Ok((U32(13), i)) =>
match decode_i8x16_shuffle_lanes(bytes, i) {
Ok((lanes, next)) => Ok((i8x16_shuffle_from_lanes(lanes), next))
Err(t) => Err(t)
}
Ok((@lib.U32(14), i)) => Ok((Instruction::i8x16_swizzle(), i))
Ok((@lib.U32(15), i)) => Ok((Instruction::i8x16_splat(), i))
Ok((@lib.U32(16), i)) => Ok((Instruction::i16x8_splat(), i))
Ok((@lib.U32(17), i)) => Ok((Instruction::i32x4_splat(), i))
Ok((@lib.U32(18), i)) => Ok((Instruction::i64x2_splat(), i))
Ok((@lib.U32(19), i)) => Ok((Instruction::f32x4_splat(), i))
Ok((@lib.U32(20), i)) => Ok((Instruction::f64x2_splat(), i))
Ok((@lib.U32(35), i)) => Ok((Instruction::i8x16_eq(), i))
Ok((@lib.U32(36), i)) => Ok((Instruction::i8x16_ne(), i))
Ok((@lib.U32(37), i)) => Ok((Instruction::i8x16_lt_s(), i))
Ok((@lib.U32(38), i)) => Ok((Instruction::i8x16_lt_u(), i))
Ok((@lib.U32(39), i)) => Ok((Instruction::i8x16_gt_s(), i))
Ok((@lib.U32(40), i)) => Ok((Instruction::i8x16_gt_u(), i))
Ok((@lib.U32(41), i)) => Ok((Instruction::i8x16_le_s(), i))
Ok((@lib.U32(42), i)) => Ok((Instruction::i8x16_le_u(), i))
Ok((@lib.U32(43), i)) => Ok((Instruction::i8x16_ge_s(), i))
Ok((@lib.U32(44), i)) => Ok((Instruction::i8x16_ge_u(), i))
Ok((@lib.U32(45), i)) => Ok((Instruction::i16x8_eq(), i))
Ok((@lib.U32(46), i)) => Ok((Instruction::i16x8_ne(), i))
Ok((@lib.U32(47), i)) => Ok((Instruction::i16x8_lt_s(), i))
Ok((@lib.U32(48), i)) => Ok((Instruction::i16x8_lt_u(), i))
Ok((@lib.U32(49), i)) => Ok((Instruction::i16x8_gt_s(), i))
Ok((@lib.U32(50), i)) => Ok((Instruction::i16x8_gt_u(), i))
Ok((@lib.U32(51), i)) => Ok((Instruction::i16x8_le_s(), i))
Ok((@lib.U32(52), i)) => Ok((Instruction::i16x8_le_u(), i))
Ok((@lib.U32(53), i)) => Ok((Instruction::i16x8_ge_s(), i))
Ok((@lib.U32(54), i)) => Ok((Instruction::i16x8_ge_u(), i))
Ok((@lib.U32(55), i)) => Ok((Instruction::i32x4_eq(), i))
Ok((@lib.U32(56), i)) => Ok((Instruction::i32x4_ne(), i))
Ok((@lib.U32(57), i)) => Ok((Instruction::i32x4_lt_s(), i))
Ok((@lib.U32(58), i)) => Ok((Instruction::i32x4_lt_u(), i))
Ok((@lib.U32(59), i)) => Ok((Instruction::i32x4_gt_s(), i))
Ok((@lib.U32(60), i)) => Ok((Instruction::i32x4_gt_u(), i))
Ok((@lib.U32(61), i)) => Ok((Instruction::i32x4_le_s(), i))
Ok((@lib.U32(62), i)) => Ok((Instruction::i32x4_le_u(), i))
Ok((@lib.U32(63), i)) => Ok((Instruction::i32x4_ge_s(), i))
Ok((@lib.U32(64), i)) => Ok((Instruction::i32x4_ge_u(), i))
Ok((@lib.U32(65), i)) => Ok((Instruction::f32x4_eq(), i))
Ok((@lib.U32(66), i)) => Ok((Instruction::f32x4_ne(), i))
Ok((@lib.U32(67), i)) => Ok((Instruction::f32x4_lt(), i))
Ok((@lib.U32(68), i)) => Ok((Instruction::f32x4_gt(), i))
Ok((@lib.U32(69), i)) => Ok((Instruction::f32x4_le(), i))
Ok((@lib.U32(70), i)) => Ok((Instruction::f32x4_ge(), i))
Ok((@lib.U32(71), i)) => Ok((Instruction::f64x2_eq(), i))
Ok((@lib.U32(72), i)) => Ok((Instruction::f64x2_ne(), i))
Ok((@lib.U32(73), i)) => Ok((Instruction::f64x2_lt(), i))
Ok((@lib.U32(74), i)) => Ok((Instruction::f64x2_gt(), i))
Ok((@lib.U32(75), i)) => Ok((Instruction::f64x2_le(), i))
Ok((@lib.U32(76), i)) => Ok((Instruction::f64x2_ge(), i))
Ok((@lib.U32(77), i)) => Ok((Instruction::v128_not(), i))
Ok((@lib.U32(78), i)) => Ok((Instruction::v128_and(), i))
Ok((@lib.U32(79), i)) => Ok((Instruction::v128_andnot(), i))
Ok((@lib.U32(80), i)) => Ok((Instruction::v128_or(), i))
Ok((@lib.U32(81), i)) => Ok((Instruction::v128_xor(), i))
Ok((@lib.U32(82), i)) => Ok((Instruction::v128_bitselect(), i))
Ok((@lib.U32(83), i)) => Ok((Instruction::v128_any_true(), i))
Ok((@lib.U32(94), i)) => Ok((Instruction::f32x4_demote_f64x2_zero(), i))
Ok((@lib.U32(95), i)) => Ok((Instruction::f64x2_promote_low_f32x4(), i))
Ok((@lib.U32(96), i)) => Ok((Instruction::i8x16_abs(), i))
Ok((@lib.U32(97), i)) => Ok((Instruction::i8x16_neg(), i))
Ok((@lib.U32(98), i)) => Ok((Instruction::i8x16_popcnt(), i))
Ok((@lib.U32(99), i)) => Ok((Instruction::i8x16_all_true(), i))
Ok((@lib.U32(100), i)) => Ok((Instruction::i8x16_bitmask(), i))
Ok((@lib.U32(101), i)) => Ok((Instruction::i8x16_narrow_i16x8s(), i))
Ok((@lib.U32(102), i)) => Ok((Instruction::i8x16_narrow_i16x8u(), i))
Ok((@lib.U32(103), i)) => Ok((Instruction::f32x4_ceil(), i))
Ok((@lib.U32(104), i)) => Ok((Instruction::f32x4_floor(), i))
Ok((@lib.U32(105), i)) => Ok((Instruction::f32x4_trunc(), i))
Ok((@lib.U32(106), i)) => Ok((Instruction::f32x4_nearest(), i))
Ok((@lib.U32(107), i)) => Ok((Instruction::i8x16_shl(), i))
Ok((@lib.U32(108), i)) => Ok((Instruction::i8x16_shr_s(), i))
Ok((@lib.U32(109), i)) => Ok((Instruction::i8x16_shr_u(), i))
Ok((@lib.U32(110), i)) => Ok((Instruction::i8x16_add(), i))
Ok((@lib.U32(111), i)) => Ok((Instruction::i8x16_add_sat_s(), i))
Ok((@lib.U32(112), i)) => Ok((Instruction::i8x16_add_sat_u(), i))
Ok((@lib.U32(113), i)) => Ok((Instruction::i8x16_sub(), i))
Ok((@lib.U32(114), i)) => Ok((Instruction::i8x16_sub_sat_s(), i))
Ok((@lib.U32(115), i)) => Ok((Instruction::i8x16_sub_sat_u(), i))
Ok((@lib.U32(116), i)) => Ok((Instruction::f64x2_ceil(), i))
Ok((@lib.U32(117), i)) => Ok((Instruction::f64x2_floor(), i))
Ok((@lib.U32(118), i)) => Ok((Instruction::i8x16_min_s(), i))
Ok((@lib.U32(119), i)) => Ok((Instruction::i8x16_min_u(), i))
Ok((@lib.U32(120), i)) => Ok((Instruction::i8x16_max_s(), i))
Ok((@lib.U32(121), i)) => Ok((Instruction::i8x16_max_u(), i))
Ok((@lib.U32(122), i)) => Ok((Instruction::f64x2_trunc(), i))
Ok((@lib.U32(123), i)) => Ok((Instruction::i8x16_avgr_u(), i))
Ok((@lib.U32(124), i)) =>
Ok((Instruction::i16x8_extadd_pairwise_i8x16s(), i))
Ok((@lib.U32(125), i)) =>
Ok((Instruction::i16x8_extadd_pairwise_i8x16u(), i))
Ok((@lib.U32(126), i)) =>
Ok((Instruction::i32x4_extadd_pairwise_i16x8s(), i))
Ok((@lib.U32(127), i)) =>
Ok((Instruction::i32x4_extadd_pairwise_i16x8u(), i))
Ok((@lib.U32(128), i)) => Ok((Instruction::i16x8_abs(), i))
Ok((@lib.U32(129), i)) => Ok((Instruction::i16x8_neg(), i))
Ok((@lib.U32(130), i)) => Ok((Instruction::i16x8q15mulr_sat_s(), i))
Ok((@lib.U32(131), i)) => Ok((Instruction::i16x8_all_true(), i))
Ok((@lib.U32(132), i)) => Ok((Instruction::i16x8_bitmask(), i))
Ok((@lib.U32(133), i)) => Ok((Instruction::i16x8_narrow_i32x4s(), i))
Ok((@lib.U32(134), i)) => Ok((Instruction::i16x8_narrow_i32x4u(), i))
Ok((@lib.U32(135), i)) =>
Ok((Instruction::i16x8_extend_low_i8x16s(), i))
Ok((@lib.U32(136), i)) =>
Ok((Instruction::i16x8_extend_high_i8x16s(), i))
Ok((@lib.U32(137), i)) =>
Ok((Instruction::i16x8_extend_low_i8x16u(), i))
Ok((@lib.U32(138), i)) =>
Ok((Instruction::i16x8_extend_high_i8x16u(), i))
Ok((@lib.U32(139), i)) => Ok((Instruction::i16x8_shl(), i))
Ok((@lib.U32(140), i)) => Ok((Instruction::i16x8_shr_s(), i))
Ok((@lib.U32(141), i)) => Ok((Instruction::i16x8_shr_u(), i))
Ok((@lib.U32(142), i)) => Ok((Instruction::i16x8_add(), i))
Ok((@lib.U32(143), i)) => Ok((Instruction::i16x8_add_sat_s(), i))
Ok((@lib.U32(144), i)) => Ok((Instruction::i16x8_add_sat_u(), i))
Ok((@lib.U32(145), i)) => Ok((Instruction::i16x8_sub(), i))
Ok((@lib.U32(146), i)) => Ok((Instruction::i16x8_sub_sat_s(), i))
Ok((@lib.U32(147), i)) => Ok((Instruction::i16x8_sub_sat_u(), i))
Ok((@lib.U32(148), i)) => Ok((Instruction::f64x2_nearest(), i))
Ok((@lib.U32(149), i)) => Ok((Instruction::i16x8_mul(), i))
Ok((@lib.U32(150), i)) => Ok((Instruction::i16x8_min_s(), i))
Ok((@lib.U32(151), i)) => Ok((Instruction::i16x8_min_u(), i))
Ok((@lib.U32(152), i)) => Ok((Instruction::i16x8_max_s(), i))
Ok((@lib.U32(153), i)) => Ok((Instruction::i16x8_max_u(), i))
Ok((@lib.U32(155), i)) => Ok((Instruction::i16x8_avgr_u(), i))
Ok((@lib.U32(156), i)) =>
Ok((Instruction::i16x8_extmul_low_i8x16s(), i))
Ok((@lib.U32(157), i)) =>
Ok((Instruction::i16x8_extmul_high_i8x16s(), i))
Ok((@lib.U32(158), i)) =>
Ok((Instruction::i16x8_extmul_low_i8x16u(), i))
Ok((@lib.U32(159), i)) =>
Ok((Instruction::i16x8_extmul_high_i8x16u(), i))
Ok((@lib.U32(160), i)) => Ok((Instruction::i32x4_abs(), i))
Ok((@lib.U32(161), i)) => Ok((Instruction::i32x4_neg(), i))
Ok((@lib.U32(163), i)) => Ok((Instruction::i32x4_all_true(), i))
Ok((@lib.U32(164), i)) => Ok((Instruction::i32x4_bitmask(), i))
Ok((@lib.U32(167), i)) =>
Ok((Instruction::i32x4_extend_low_i16x8s(), i))
Ok((@lib.U32(168), i)) =>
Ok((Instruction::i32x4_extend_high_i16x8s(), i))
Ok((@lib.U32(169), i)) =>
Ok((Instruction::i32x4_extend_low_i16x8u(), i))
Ok((@lib.U32(170), i)) =>
Ok((Instruction::i32x4_extend_high_i16x8u(), i))
Ok((@lib.U32(171), i)) => Ok((Instruction::i32x4_shl(), i))
Ok((@lib.U32(172), i)) => Ok((Instruction::i32x4_shr_s(), i))
Ok((@lib.U32(173), i)) => Ok((Instruction::i32x4_shr_u(), i))
Ok((@lib.U32(174), i)) => Ok((Instruction::i32x4_add(), i))
Ok((@lib.U32(177), i)) => Ok((Instruction::i32x4_sub(), i))
Ok((@lib.U32(181), i)) => Ok((Instruction::i32x4_mul(), i))
Ok((@lib.U32(182), i)) => Ok((Instruction::i32x4_min_s(), i))
Ok((@lib.U32(183), i)) => Ok((Instruction::i32x4_min_u(), i))
Ok((@lib.U32(184), i)) => Ok((Instruction::i32x4_max_s(), i))
Ok((@lib.U32(185), i)) => Ok((Instruction::i32x4_max_u(), i))
Ok((@lib.U32(186), i)) => Ok((Instruction::i32x4_dot_i16x8s(), i))
Ok((@lib.U32(188), i)) =>
Ok((Instruction::i32x4_extmul_low_i16x8s(), i))
Ok((@lib.U32(189), i)) =>
Ok((Instruction::i32x4_extmul_high_i16x8s(), i))
Ok((@lib.U32(190), i)) =>
Ok((Instruction::i32x4_extmul_low_i16x8u(), i))
Ok((@lib.U32(191), i)) =>
Ok((Instruction::i32x4_extmul_high_i16x8u(), i))
Ok((@lib.U32(192), i)) => Ok((Instruction::i64x2_abs(), i))
Ok((@lib.U32(193), i)) => Ok((Instruction::i64x2_neg(), i))
Ok((@lib.U32(195), i)) => Ok((Instruction::i64x2_all_true(), i))
Ok((@lib.U32(196), i)) => Ok((Instruction::i64x2_bitmask(), i))
Ok((@lib.U32(199), i)) =>
Ok((Instruction::i64x2_extend_low_i32x4s(), i))
Ok((@lib.U32(200), i)) =>
Ok((Instruction::i64x2_extend_high_i32x4s(), i))
Ok((@lib.U32(201), i)) =>
Ok((Instruction::i64x2_extend_low_i32x4u(), i))
Ok((@lib.U32(202), i)) =>
Ok((Instruction::i64x2_extend_high_i32x4u(), i))
Ok((@lib.U32(203), i)) => Ok((Instruction::i64x2_shl(), i))
Ok((@lib.U32(204), i)) => Ok((Instruction::i64x2_shr_s(), i))
Ok((@lib.U32(205), i)) => Ok((Instruction::i64x2_shr_u(), i))
Ok((@lib.U32(206), i)) => Ok((Instruction::i64x2_add(), i))
Ok((@lib.U32(209), i)) => Ok((Instruction::i64x2_sub(), i))
Ok((@lib.U32(213), i)) => Ok((Instruction::i64x2_mul(), i))
Ok((@lib.U32(214), i)) => Ok((Instruction::i64x2_eq(), i))
Ok((@lib.U32(215), i)) => Ok((Instruction::i64x2_ne(), i))
Ok((@lib.U32(216), i)) => Ok((Instruction::i64x2_lt_s(), i))
Ok((@lib.U32(217), i)) => Ok((Instruction::i64x2_gt_s(), i))
Ok((@lib.U32(218), i)) => Ok((Instruction::i64x2_le_s(), i))
Ok((@lib.U32(219), i)) => Ok((Instruction::i64x2_ge_s(), i))
Ok((@lib.U32(220), i)) =>
Ok((Instruction::i64x2_extmul_low_i32x4s(), i))
Ok((@lib.U32(221), i)) =>
Ok((Instruction::i64x2_extmul_high_i32x4s(), i))
Ok((@lib.U32(222), i)) =>
Ok((Instruction::i64x2_extmul_low_i32x4u(), i))
Ok((@lib.U32(223), i)) =>
Ok((Instruction::i64x2_extmul_high_i32x4u(), i))
Ok((@lib.U32(224), i)) => Ok((Instruction::f32x4_abs(), i))
Ok((@lib.U32(225), i)) => Ok((Instruction::f32x4_neg(), i))
Ok((@lib.U32(227), i)) => Ok((Instruction::f32x4_sqrt(), i))
Ok((@lib.U32(228), i)) => Ok((Instruction::f32x4_add(), i))
Ok((@lib.U32(229), i)) => Ok((Instruction::f32x4_sub(), i))
Ok((@lib.U32(230), i)) => Ok((Instruction::f32x4_mul(), i))
Ok((@lib.U32(231), i)) => Ok((Instruction::f32x4_div(), i))
Ok((@lib.U32(232), i)) => Ok((Instruction::f32x4_min(), i))
Ok((@lib.U32(233), i)) => Ok((Instruction::f32x4_max(), i))
Ok((@lib.U32(234), i)) => Ok((Instruction::f32x4_pmin(), i))
Ok((@lib.U32(235), i)) => Ok((Instruction::f32x4_pmax(), i))
Ok((@lib.U32(236), i)) => Ok((Instruction::f64x2_abs(), i))
Ok((@lib.U32(237), i)) => Ok((Instruction::f64x2_neg(), i))
Ok((@lib.U32(239), i)) => Ok((Instruction::f64x2_sqrt(), i))
Ok((@lib.U32(240), i)) => Ok((Instruction::f64x2_add(), i))
Ok((@lib.U32(241), i)) => Ok((Instruction::f64x2_sub(), i))
Ok((@lib.U32(242), i)) => Ok((Instruction::f64x2_mul(), i))
Ok((@lib.U32(243), i)) => Ok((Instruction::f64x2_div(), i))
Ok((@lib.U32(244), i)) => Ok((Instruction::f64x2_min(), i))
Ok((@lib.U32(245), i)) => Ok((Instruction::f64x2_max(), i))
Ok((@lib.U32(246), i)) => Ok((Instruction::f64x2_pmin(), i))
Ok((@lib.U32(247), i)) => Ok((Instruction::f64x2_pmax(), i))
Ok((@lib.U32(248), i)) => Ok((Instruction::i32x4_trunc_sat_f32x4s(), i))
Ok((@lib.U32(249), i)) => Ok((Instruction::i32x4_trunc_sat_f32x4u(), i))
Ok((@lib.U32(250), i)) => Ok((Instruction::f32x4_convert_i32x4s(), i))
Ok((@lib.U32(251), i)) => Ok((Instruction::f32x4_convert_i32x4u(), i))
Ok((@lib.U32(252), i)) =>
Ok((Instruction::i32x4_trunc_sat_f64x2s_zero(), i))
Ok((@lib.U32(253), i)) =>
Ok((Instruction::i32x4_trunc_sat_f64x2u_zero(), i))
Ok((@lib.U32(254), i)) =>
Ok((Instruction::f64x2_convert_low_i32x4s(), i))
Ok((@lib.U32(255), i)) =>
Ok((Instruction::f64x2_convert_low_i32x4u(), i))
Ok((@lib.U32(256), i)) => Ok((Instruction::i8x16_relaxed_swizzle(), i))
Ok((@lib.U32(257), i)) =>
Ok((Instruction::i32x4_relaxed_trunc_f32x4s(), i))
Ok((@lib.U32(258), i)) =>
Ok((Instruction::i32x4_relaxed_trunc_f32x4u(), i))
Ok((@lib.U32(259), i)) =>
Ok((Instruction::i32x4_relaxed_trunc_zero_f64x2s(), i))
Ok((@lib.U32(260), i)) =>
Ok((Instruction::i32x4_relaxed_trunc_zero_f64x2u(), i))
Ok((@lib.U32(261), i)) => Ok((Instruction::f32x4_relaxed_madd(), i))
Ok((@lib.U32(262), i)) => Ok((Instruction::f32x4_relaxed_nmadd(), i))
Ok((@lib.U32(263), i)) => Ok((Instruction::f64x2_relaxed_madd(), i))
Ok((@lib.U32(264), i)) => Ok((Instruction::f64x2_relaxed_nmadd(), i))
Ok((@lib.U32(265), i)) =>
Ok((Instruction::i8x16_relaxed_laneselect(), i))
Ok((@lib.U32(266), i)) =>
Ok((Instruction::i16x8_relaxed_laneselect(), i))
Ok((@lib.U32(267), i)) =>
Ok((Instruction::i32x4_relaxed_laneselect(), i))
Ok((@lib.U32(268), i)) =>
Ok((Instruction::i64x2_relaxed_laneselect(), i))
Ok((@lib.U32(269), i)) => Ok((Instruction::f32x4_relaxed_min(), i))
Ok((@lib.U32(270), i)) => Ok((Instruction::f32x4_relaxed_max(), i))
Ok((@lib.U32(271), i)) => Ok((Instruction::f64x2_relaxed_min(), i))
Ok((@lib.U32(272), i)) => Ok((Instruction::f64x2_relaxed_max(), i))
Ok((@lib.U32(273), i)) =>
Ok((Instruction::i16x8_relaxed_q15mulr_s(), i))
Ok((@lib.U32(274), i)) =>
Ok((Instruction::i16x8_relaxed_dot_i8x16i7x16s(), i))
Ok((@lib.U32(275), i)) =>
Ok((Instruction::i32x4_relaxed_dot_i8x16i7x16_add_s(), i))
Ok((@lib.U32(21), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i8x16_extract_lane_s(l), i))
Err(t) => Err(t)
}
Ok((U32(22), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i8x16_extract_lane_u(l), i))
Err(t) => Err(t)
}
Ok((U32(23), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i8x16_replace_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(24), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i16x8_extract_lane_s(l), i))
Err(t) => Err(t)
}
Ok((U32(25), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i16x8_extract_lane_u(l), i))
Err(t) => Err(t)
}
Ok((U32(26), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i16x8_replace_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(27), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i32x4_extract_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(28), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i32x4_replace_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(29), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i64x2_extract_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(30), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::i64x2_replace_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(31), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::f32x4_extract_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(32), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::f32x4_replace_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(33), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::f64x2_extract_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(34), i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::f64x2_replace_lane(l), i))
Err(t) => Err(t)
}
Ok((U32(84), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::v128_load8_lane(m, l), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(85), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::v128_load16_lane(m, l), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(86), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::v128_load32_lane(m, l), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(87), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::v128_load64_lane(m, l), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(88), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::v128_store8_lane(m, l), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(89), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::v128_store16_lane(m, l), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(90), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::v128_store32_lane(m, l), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(91), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) =>
match Decode::decode(bytes, i) {
Ok((l, i)) => Ok((Instruction::v128_store64_lane(m, l), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
}
Ok((U32(92), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load32_zero(m), i))
Err(t) => Err(t)
}
Ok((U32(93), i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((Instruction::v128_load64_zero(m), i))
Err(t) => Err(t)
}
Err(t) => Err(t)
_ => Err(BinaryDecodeError::InvalidInstruction)
}
_ => Err(BinaryDecodeError::InvalidInstruction)
}
}
///|
pub impl Decode for Instruction with fn decode(bytes, i) {
decode_instruction_with_depth(bytes, i, 0)
}
///|
pub impl Decode for FieldType with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Err(err) => Err(err)
Ok((st, i)) =>
match Decode::decode(bytes, i) {
Ok((m, i)) => Ok((FieldType::new(st, m), i))
Err(err) => Err(err)
}
}
}
///|
pub impl[T : Decode] Decode for Array[T] with fn decode(bytes, i) {
match Decode::decode(bytes, i) {
Err(t) => Err(t)
Ok((@lib.U32(count), i)) => {
let mut remaining = count
let result : Array[T] = []
let mut pos = i
while remaining > 0 {
match T::decode(bytes, pos) {
Ok((t, next_pos)) => {
result.push(t)
pos = next_pos
remaining = remaining - 1
}
Err(t) => return Err(t)
}
}
Ok((result, pos))
}
}
}
///|
fn decode_array_memory_argument(
bytes : Bytes,
i : Int,
) -> Result[(MemArg, @lib.TypeIdx, Int), BinaryDecodeError] {
let (@lib.U32(flags), next) = match Decode::decode(bytes, i) {
Ok(value) => value
Err(err) => return Err(err)
}
if (flags & 0xfffffff0U) != 0x20U || (flags & 15U) > 8U {
return Err(BinaryDecodeError::InvalidMemArg)
}
let (ti, next) : (@lib.TypeIdx, Int) = match Decode::decode(bytes, next) {
Ok(value) => value
Err(err) => return Err(err)
}
match Decode::decode(bytes, next) {
Ok((@lib.U32(offset), next)) =>
Ok((MemArg::new(flags & 15U, None, offset.to_uint64()), ti, next))
Err(err) => Err(err)
}
}
///|
fn decode_memory_load(
bytes : Bytes,
i : Int,
op : @lib.LoadOp,
linear : (MemArg) -> Instruction,
) -> Result[(Instruction, Int), BinaryDecodeError] {
let (@lib.U32(flags), _) = match Decode::decode(bytes, i) {
Ok(value) => value
Err(err) => return Err(err)
}
if (flags & 0x20U) != 0U {
match decode_array_memory_argument(bytes, i) {
Ok((ma, ti, next)) =>
Ok((Instruction::array_load(op, ti, memarg=ma), next))
Err(err) => Err(err)
}
} else {
match Decode::decode(bytes, i) {
Ok((ma, next)) => Ok((linear(ma), next))
Err(err) => Err(err)
}
}
}
///|
fn decode_memory_store(
bytes : Bytes,
i : Int,
op : @lib.StoreOp,
linear : (MemArg) -> Instruction,
) -> Result[(Instruction, Int), BinaryDecodeError] {
let (@lib.U32(flags), _) = match Decode::decode(bytes, i) {
Ok(value) => value
Err(err) => return Err(err)
}
if (flags & 0x20U) != 0U {
match decode_array_memory_argument(bytes, i) {
Ok((ma, ti, next)) =>
Ok((Instruction::array_store(op, ti, memarg=ma), next))
Err(err) => Err(err)
}
} else {
match Decode::decode(bytes, i) {
Ok((ma, next)) => Ok((linear(ma), next))
Err(err) => Err(err)
}
}
}