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}