/src/wasm-tools/crates/wasm-encoder/src/component/imports.rs
Line | Count | Source |
1 | | use crate::{ |
2 | | ComponentExportKind, ComponentSection, ComponentSectionId, ComponentValType, Encode, |
3 | | encode_section, |
4 | | }; |
5 | | use alloc::vec::Vec; |
6 | | |
7 | | /// Represents the possible type bounds for type references. |
8 | | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] |
9 | | pub enum TypeBounds { |
10 | | /// The type is bounded by equality to the type index specified. |
11 | | Eq(u32), |
12 | | /// This type is a fresh resource type, |
13 | | SubResource, |
14 | | } |
15 | | |
16 | | impl Encode for TypeBounds { |
17 | 65.0k | fn encode(&self, sink: &mut Vec<u8>) { |
18 | 65.0k | match self { |
19 | 61.0k | Self::Eq(i) => { |
20 | 61.0k | sink.push(0x00); |
21 | 61.0k | i.encode(sink); |
22 | 61.0k | } |
23 | 3.96k | Self::SubResource => sink.push(0x01), |
24 | | } |
25 | 65.0k | } |
26 | | } |
27 | | |
28 | | /// Represents a reference to a type. |
29 | | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] |
30 | | pub enum ComponentTypeRef { |
31 | | /// The reference is to a core module type. |
32 | | /// |
33 | | /// The index is expected to be core type index to a core module type. |
34 | | Module(u32), |
35 | | /// The reference is to a function type. |
36 | | /// |
37 | | /// The index is expected to be a type index to a function type. |
38 | | Func(u32), |
39 | | /// The reference is to a value type. |
40 | | Value(ComponentValType), |
41 | | /// The reference is to a bounded type. |
42 | | Type(TypeBounds), |
43 | | /// The reference is to an instance type. |
44 | | /// |
45 | | /// The index is expected to be a type index to an instance type. |
46 | | Instance(u32), |
47 | | /// The reference is to a component type. |
48 | | /// |
49 | | /// The index is expected to be a type index to a component type. |
50 | | Component(u32), |
51 | | } |
52 | | |
53 | | impl ComponentTypeRef { |
54 | | /// Gets the export kind of the reference. |
55 | 186k | pub fn kind(&self) -> ComponentExportKind { |
56 | 186k | match self { |
57 | 0 | Self::Module(_) => ComponentExportKind::Module, |
58 | 33.1k | Self::Func(_) => ComponentExportKind::Func, |
59 | 0 | Self::Value(_) => ComponentExportKind::Value, |
60 | 65.0k | Self::Type(..) => ComponentExportKind::Type, |
61 | 66.7k | Self::Instance(_) => ComponentExportKind::Instance, |
62 | 22.0k | Self::Component(_) => ComponentExportKind::Component, |
63 | | } |
64 | 186k | } |
65 | | } |
66 | | |
67 | | impl Encode for ComponentTypeRef { |
68 | 186k | fn encode(&self, sink: &mut Vec<u8>) { |
69 | 186k | self.kind().encode(sink); |
70 | | |
71 | 186k | match self { |
72 | 121k | Self::Module(idx) | Self::Func(idx) | Self::Instance(idx) | Self::Component(idx) => { |
73 | 121k | idx.encode(sink); |
74 | 121k | } |
75 | 0 | Self::Value(ty) => ty.encode(sink), |
76 | 65.0k | Self::Type(bounds) => bounds.encode(sink), |
77 | | } |
78 | 186k | } |
79 | | } |
80 | | |
81 | | /// An encoder for the import section of WebAssembly components. |
82 | | /// |
83 | | /// # Example |
84 | | /// |
85 | | /// ```rust |
86 | | /// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType, ComponentImportSection, ComponentTypeRef}; |
87 | | /// |
88 | | /// let mut types = ComponentTypeSection::new(); |
89 | | /// |
90 | | /// // Define a function type of `[string, string] -> string`. |
91 | | /// types |
92 | | /// .function() |
93 | | /// .params( |
94 | | /// [ |
95 | | /// ("a", PrimitiveValType::String), |
96 | | /// ("b", PrimitiveValType::String) |
97 | | /// ] |
98 | | /// ) |
99 | | /// .result(Some(PrimitiveValType::String.into())); |
100 | | /// |
101 | | /// // This imports a function named `f` with the type defined above |
102 | | /// let mut imports = ComponentImportSection::new(); |
103 | | /// imports.import("f", ComponentTypeRef::Func(0)); |
104 | | /// |
105 | | /// let mut component = Component::new(); |
106 | | /// component.section(&types); |
107 | | /// component.section(&imports); |
108 | | /// |
109 | | /// let bytes = component.finish(); |
110 | | /// ``` |
111 | | #[derive(Clone, Debug, Default)] |
112 | | pub struct ComponentImportSection { |
113 | | bytes: Vec<u8>, |
114 | | num_added: u32, |
115 | | } |
116 | | |
117 | | impl ComponentImportSection { |
118 | | /// Create a new component import section encoder. |
119 | 5.23k | pub fn new() -> Self { |
120 | 5.23k | Self::default() |
121 | 5.23k | } |
122 | | |
123 | | /// The number of imports in the section. |
124 | 0 | pub fn len(&self) -> u32 { |
125 | 0 | self.num_added |
126 | 0 | } |
127 | | |
128 | | /// Determines if the section is empty. |
129 | 0 | pub fn is_empty(&self) -> bool { |
130 | 0 | self.num_added == 0 |
131 | 0 | } |
132 | | |
133 | | /// Define an import in the component import section. |
134 | 5.90k | pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self { |
135 | 5.90k | encode_component_import_name(&mut self.bytes, name); |
136 | 5.90k | ty.encode(&mut self.bytes); |
137 | 5.90k | self.num_added += 1; |
138 | 5.90k | self |
139 | 5.90k | } |
140 | | } |
141 | | |
142 | | impl Encode for ComponentImportSection { |
143 | 5.23k | fn encode(&self, sink: &mut Vec<u8>) { |
144 | 5.23k | encode_section(sink, self.num_added, &self.bytes); |
145 | 5.23k | } |
146 | | } |
147 | | |
148 | | impl ComponentSection for ComponentImportSection { |
149 | 5.23k | fn id(&self) -> u8 { |
150 | 5.23k | ComponentSectionId::Import.into() |
151 | 5.23k | } |
152 | | } |
153 | | |
154 | | /// Prior to WebAssembly/component-model#263 import and export names were |
155 | | /// discriminated with a leading byte indicating what kind of import they are. |
156 | | /// After that PR though names are always prefixed with a 0x00 byte. |
157 | | /// |
158 | | /// On 2023-10-28 in bytecodealliance/wasm-tools#1262 was landed to start |
159 | | /// transitioning to "always lead with 0x00". That updated the validator/parser |
160 | | /// to accept either 0x00 or 0x01 but the encoder wasn't updated at the time. |
161 | | /// |
162 | | /// On 2024-09-03 in bytecodealliance/wasm-tools#TODO this encoder was updated |
163 | | /// to always emit 0x00 as a leading byte. |
164 | | /// |
165 | | /// This function corresponds with the `importname'` production in the |
166 | | /// specification. |
167 | 38.4k | pub(crate) fn encode_component_import_name(bytes: &mut Vec<u8>, name: &str) { |
168 | 38.4k | bytes.push(0x00); |
169 | 38.4k | name.encode(bytes); |
170 | 38.4k | } |