wasmparser/readers/component/
imports.rs

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