1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
use crate::{
BinaryReader, ComponentExternalKind, ComponentValType, FromReader, Result, SectionLimited,
};
/// Represents the type bounds for imports and exports.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TypeBounds {
/// The type is bounded by equality.
Eq(u32),
/// A fresh resource type,
SubResource,
}
impl<'a> FromReader<'a> for TypeBounds {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
Ok(match reader.read_u8()? {
0x00 => TypeBounds::Eq(reader.read()?),
0x01 => TypeBounds::SubResource,
x => return reader.invalid_leading_byte(x, "type bound"),
})
}
}
/// Represents a reference to a component type.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ComponentTypeRef {
/// The reference is to a core module type.
///
/// The index is expected to be core type index to a core module type.
Module(u32),
/// The reference is to a function type.
///
/// The index is expected to be a type index to a function type.
Func(u32),
/// The reference is to a value type.
Value(ComponentValType),
/// The reference is to a bounded type.
///
/// The index is expected to be a type index.
Type(TypeBounds),
/// The reference is to an instance type.
///
/// The index is a type index to an instance type.
Instance(u32),
/// The reference is to a component type.
///
/// The index is a type index to a component type.
Component(u32),
}
impl ComponentTypeRef {
/// Returns the corresponding [`ComponentExternalKind`] for this reference.
pub fn kind(&self) -> ComponentExternalKind {
match self {
ComponentTypeRef::Module(_) => ComponentExternalKind::Module,
ComponentTypeRef::Func(_) => ComponentExternalKind::Func,
ComponentTypeRef::Value(_) => ComponentExternalKind::Value,
ComponentTypeRef::Type(..) => ComponentExternalKind::Type,
ComponentTypeRef::Instance(_) => ComponentExternalKind::Instance,
ComponentTypeRef::Component(_) => ComponentExternalKind::Component,
}
}
}
impl<'a> FromReader<'a> for ComponentTypeRef {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
Ok(match reader.read()? {
ComponentExternalKind::Module => ComponentTypeRef::Module(reader.read()?),
ComponentExternalKind::Func => ComponentTypeRef::Func(reader.read()?),
ComponentExternalKind::Value => ComponentTypeRef::Value(reader.read()?),
ComponentExternalKind::Type => ComponentTypeRef::Type(reader.read()?),
ComponentExternalKind::Instance => ComponentTypeRef::Instance(reader.read()?),
ComponentExternalKind::Component => ComponentTypeRef::Component(reader.read()?),
})
}
}
/// Represents an import in a WebAssembly component
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ComponentImport<'a> {
/// The name of the imported item.
pub name: ComponentImportName<'a>,
/// The type reference for the import.
pub ty: ComponentTypeRef,
}
impl<'a> FromReader<'a> for ComponentImport<'a> {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
Ok(ComponentImport {
name: reader.read()?,
ty: reader.read()?,
})
}
}
/// A reader for the import section of a WebAssembly component.
///
/// # Examples
///
/// ```
/// use wasmparser::{ComponentImportSectionReader, BinaryReader};
/// let data: &[u8] = &[0x01, 0x00, 0x01, 0x41, 0x01, 0x66];
/// let reader = BinaryReader::new(data, 0);
/// let reader = ComponentImportSectionReader::new(reader).unwrap();
/// for import in reader {
/// let import = import.expect("import");
/// println!("Import: {:?}", import);
/// }
/// ```
pub type ComponentImportSectionReader<'a> = SectionLimited<'a, ComponentImport<'a>>;
/// Represents the name of a component import.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[allow(missing_docs)]
pub struct ComponentImportName<'a>(pub &'a str);
impl<'a> FromReader<'a> for ComponentImportName<'a> {
fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
match reader.read_u8()? {
// This is the spec-required byte as of this time.
0x00 => {}
// Prior to WebAssembly/component-model#263 export names used a
// discriminator byte of 0x01 to indicate an "interface" of the
// form `a:b/c` but nowadays that's inferred from string syntax.
// Ignore 0-vs-1 to continue to parse older binaries. Eventually
// this will go away.
//
// This logic to ignore 0x01 was landed on 2023-10-28 in
// bytecodealliance/wasm-tools#1262 and the encoder at the time
// still emitted 0x01 to have better compatibility with prior
// validators.
//
// On 2024-09-03 in bytecodealliance/wasm-tools#TODO the encoder
// was updated to always emit 0x00 as a leading byte. After enough
// time has passed this case may be able to be removed. When
// removing this it's probably best to do it with a `WasmFeatures`
// flag first to ensure there's an opt-in way of fixing things.
0x01 => {}
x => return reader.invalid_leading_byte(x, "import name"),
}
Ok(ComponentImportName(reader.read_string()?))
}
}