1 | use 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)] |
7 | pub enum TypeBounds { |
8 | /// The type is bounded by equality. |
9 | Eq(u32), |
10 | /// A fresh resource type, |
11 | SubResource, |
12 | } |
13 | |
14 | impl<'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: u8 => return reader.invalid_leading_byte(byte:x, desc:"type bound" ), |
20 | }) |
21 | } |
22 | } |
23 | |
24 | /// Represents a reference to a component type. |
25 | #[derive (Clone, Copy, Debug, Eq, PartialEq)] |
26 | pub 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 | |
51 | impl 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 | |
65 | impl<'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)] |
80 | pub 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 | |
87 | impl<'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 | /// ``` |
110 | pub 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)] |
115 | pub struct ComponentImportName<'a>(pub &'a str); |
116 | |
117 | impl<'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 | } |
146 | |