1 | use crate::component::*; |
2 | use crate::{ExportKind, Module, RawSection, ValType}; |
3 | use std::mem; |
4 | |
5 | /// Convenience type to build a component incrementally and automatically keep |
6 | /// track of index spaces. |
7 | /// |
8 | /// This type is intended to be a wrapper around the [`Component`] encoding type |
9 | /// which is useful for building it up incrementally over time. This type will |
10 | /// automatically collect definitions into sections and reports the index of all |
11 | /// items added by keeping track of indices internally. |
12 | #[derive (Debug, Default)] |
13 | pub struct ComponentBuilder { |
14 | /// The binary component that's being built. |
15 | component: Component, |
16 | |
17 | /// The last section which was appended to during encoding. This type is |
18 | /// generated by the `section_accessors` macro below. |
19 | /// |
20 | /// When something is encoded this is used if it matches the kind of item |
21 | /// being encoded, otherwise it's "flushed" to the output component and a |
22 | /// new section is started. |
23 | last_section: LastSection, |
24 | |
25 | // Core index spaces |
26 | core_modules: u32, |
27 | core_funcs: u32, |
28 | core_types: u32, |
29 | core_memories: u32, |
30 | core_tables: u32, |
31 | core_instances: u32, |
32 | core_tags: u32, |
33 | core_globals: u32, |
34 | |
35 | // Component index spaces |
36 | funcs: u32, |
37 | instances: u32, |
38 | types: u32, |
39 | components: u32, |
40 | values: u32, |
41 | } |
42 | |
43 | impl ComponentBuilder { |
44 | /// Returns the current number of core modules. |
45 | pub fn core_module_count(&self) -> u32 { |
46 | self.core_modules |
47 | } |
48 | |
49 | /// Returns the current number of core funcs. |
50 | pub fn core_func_count(&self) -> u32 { |
51 | self.core_funcs |
52 | } |
53 | |
54 | /// Returns the current number of core types. |
55 | pub fn core_type_count(&self) -> u32 { |
56 | self.core_types |
57 | } |
58 | |
59 | /// Returns the current number of core memories. |
60 | pub fn core_memory_count(&self) -> u32 { |
61 | self.core_memories |
62 | } |
63 | |
64 | /// Returns the current number of core tables. |
65 | pub fn core_table_count(&self) -> u32 { |
66 | self.core_tables |
67 | } |
68 | |
69 | /// Returns the current number of core instances. |
70 | pub fn core_instance_count(&self) -> u32 { |
71 | self.core_instances |
72 | } |
73 | |
74 | /// Returns the current number of core tags. |
75 | pub fn core_tag_count(&self) -> u32 { |
76 | self.core_tags |
77 | } |
78 | |
79 | /// Returns the current number of core globals. |
80 | pub fn core_global_count(&self) -> u32 { |
81 | self.core_globals |
82 | } |
83 | |
84 | /// Returns the current number of component funcs. |
85 | pub fn func_count(&self) -> u32 { |
86 | self.funcs |
87 | } |
88 | |
89 | /// Returns the current number of component instances. |
90 | pub fn instance_count(&self) -> u32 { |
91 | self.instances |
92 | } |
93 | |
94 | /// Returns the current number of component values. |
95 | pub fn value_count(&self) -> u32 { |
96 | self.values |
97 | } |
98 | |
99 | /// Returns the current number of components. |
100 | pub fn component_count(&self) -> u32 { |
101 | self.components |
102 | } |
103 | |
104 | /// Returns the current number of component types. |
105 | pub fn type_count(&self) -> u32 { |
106 | self.types |
107 | } |
108 | |
109 | /// Completes this component and returns the binary encoding of the entire |
110 | /// component. |
111 | pub fn finish(mut self) -> Vec<u8> { |
112 | self.flush(); |
113 | self.component.finish() |
114 | } |
115 | |
116 | /// Encodes a core wasm `Module` into this component, returning its index. |
117 | pub fn core_module(&mut self, module: &Module) -> u32 { |
118 | self.flush(); |
119 | self.component.section(&ModuleSection(module)); |
120 | inc(&mut self.core_modules) |
121 | } |
122 | |
123 | /// Encodes a core wasm `module` into this component, returning its index. |
124 | pub fn core_module_raw(&mut self, module: &[u8]) -> u32 { |
125 | self.flush(); |
126 | self.component.section(&RawSection { |
127 | id: ComponentSectionId::CoreModule.into(), |
128 | data: module, |
129 | }); |
130 | inc(&mut self.core_modules) |
131 | } |
132 | |
133 | /// Instantiates a core wasm module at `module_index` with the `args` |
134 | /// provided. |
135 | /// |
136 | /// Returns the index of the core wasm instance crated. |
137 | pub fn core_instantiate<'a, A>(&mut self, module_index: u32, args: A) -> u32 |
138 | where |
139 | A: IntoIterator<Item = (&'a str, ModuleArg)>, |
140 | A::IntoIter: ExactSizeIterator, |
141 | { |
142 | self.instances().instantiate(module_index, args); |
143 | inc(&mut self.core_instances) |
144 | } |
145 | |
146 | /// Creates a new core wasm instance from the `exports` provided. |
147 | /// |
148 | /// Returns the index of the core wasm instance crated. |
149 | pub fn core_instantiate_exports<'a, E>(&mut self, exports: E) -> u32 |
150 | where |
151 | E: IntoIterator<Item = (&'a str, ExportKind, u32)>, |
152 | E::IntoIter: ExactSizeIterator, |
153 | { |
154 | self.instances().export_items(exports); |
155 | inc(&mut self.core_instances) |
156 | } |
157 | |
158 | /// Creates a new aliased item where the core `instance` specified has its |
159 | /// export `name` aliased out with the `kind` specified. |
160 | /// |
161 | /// Returns the index of the item crated. |
162 | pub fn core_alias_export(&mut self, instance: u32, name: &str, kind: ExportKind) -> u32 { |
163 | self.alias(Alias::CoreInstanceExport { |
164 | instance, |
165 | kind, |
166 | name, |
167 | }) |
168 | } |
169 | |
170 | /// Adds a new alias to this component |
171 | pub fn alias(&mut self, alias: Alias<'_>) -> u32 { |
172 | self.aliases().alias(alias); |
173 | match alias { |
174 | Alias::InstanceExport { kind, .. } => self.inc_kind(kind), |
175 | Alias::CoreInstanceExport { kind, .. } => self.inc_core_kind(kind), |
176 | Alias::Outer { |
177 | kind: ComponentOuterAliasKind::Type, |
178 | .. |
179 | } => inc(&mut self.types), |
180 | Alias::Outer { |
181 | kind: ComponentOuterAliasKind::CoreModule, |
182 | .. |
183 | } => inc(&mut self.core_modules), |
184 | Alias::Outer { |
185 | kind: ComponentOuterAliasKind::Component, |
186 | .. |
187 | } => inc(&mut self.components), |
188 | Alias::Outer { |
189 | kind: ComponentOuterAliasKind::CoreType, |
190 | .. |
191 | } => inc(&mut self.core_types), |
192 | } |
193 | } |
194 | |
195 | /// Creates an alias to a previous component instance's exported item. |
196 | /// |
197 | /// The `instance` provided is the instance to access and the `name` is the |
198 | /// item to access. |
199 | /// |
200 | /// Returns the index of the new item defined. |
201 | pub fn alias_export(&mut self, instance: u32, name: &str, kind: ComponentExportKind) -> u32 { |
202 | self.alias(Alias::InstanceExport { |
203 | instance, |
204 | kind, |
205 | name, |
206 | }) |
207 | } |
208 | |
209 | fn inc_kind(&mut self, kind: ComponentExportKind) -> u32 { |
210 | match kind { |
211 | ComponentExportKind::Func => inc(&mut self.funcs), |
212 | ComponentExportKind::Module => inc(&mut self.core_modules), |
213 | ComponentExportKind::Type => inc(&mut self.types), |
214 | ComponentExportKind::Component => inc(&mut self.components), |
215 | ComponentExportKind::Instance => inc(&mut self.instances), |
216 | ComponentExportKind::Value => inc(&mut self.values), |
217 | } |
218 | } |
219 | |
220 | fn inc_core_kind(&mut self, kind: ExportKind) -> u32 { |
221 | match kind { |
222 | ExportKind::Func => inc(&mut self.core_funcs), |
223 | ExportKind::Table => inc(&mut self.core_tables), |
224 | ExportKind::Memory => inc(&mut self.core_memories), |
225 | ExportKind::Global => inc(&mut self.core_globals), |
226 | ExportKind::Tag => inc(&mut self.core_tags), |
227 | } |
228 | } |
229 | |
230 | /// Lowers the `func_index` component function into a core wasm function |
231 | /// using the `options` provided. |
232 | /// |
233 | /// Returns the index of the core wasm function created. |
234 | pub fn lower_func<O>(&mut self, func_index: u32, options: O) -> u32 |
235 | where |
236 | O: IntoIterator<Item = CanonicalOption>, |
237 | O::IntoIter: ExactSizeIterator, |
238 | { |
239 | self.canonical_functions().lower(func_index, options); |
240 | inc(&mut self.core_funcs) |
241 | } |
242 | |
243 | /// Lifts the core wasm `core_func_index` function with the component |
244 | /// function type `type_index` and `options`. |
245 | /// |
246 | /// Returns the index of the component function created. |
247 | pub fn lift_func<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> u32 |
248 | where |
249 | O: IntoIterator<Item = CanonicalOption>, |
250 | O::IntoIter: ExactSizeIterator, |
251 | { |
252 | self.canonical_functions() |
253 | .lift(core_func_index, type_index, options); |
254 | inc(&mut self.funcs) |
255 | } |
256 | |
257 | /// Imports a new item into this component with the `name` and `ty` specified. |
258 | pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> u32 { |
259 | let ret = match &ty { |
260 | ComponentTypeRef::Instance(_) => inc(&mut self.instances), |
261 | ComponentTypeRef::Func(_) => inc(&mut self.funcs), |
262 | ComponentTypeRef::Type(..) => inc(&mut self.types), |
263 | ComponentTypeRef::Component(_) => inc(&mut self.components), |
264 | ComponentTypeRef::Module(_) => inc(&mut self.core_modules), |
265 | ComponentTypeRef::Value(_) => inc(&mut self.values), |
266 | }; |
267 | self.imports().import(name, ty); |
268 | ret |
269 | } |
270 | |
271 | /// Exports a new item from this component with the `name` and `kind` |
272 | /// specified. |
273 | /// |
274 | /// The `idx` is the item to export and the `ty` is an optional type to |
275 | /// ascribe to the export. |
276 | pub fn export( |
277 | &mut self, |
278 | name: &str, |
279 | kind: ComponentExportKind, |
280 | idx: u32, |
281 | ty: Option<ComponentTypeRef>, |
282 | ) -> u32 { |
283 | self.exports().export(name, kind, idx, ty); |
284 | self.inc_kind(kind) |
285 | } |
286 | |
287 | /// Creates a new encoder for the next core type in this component. |
288 | pub fn core_type(&mut self) -> (u32, ComponentCoreTypeEncoder<'_>) { |
289 | (inc(&mut self.core_types), self.core_types().ty()) |
290 | } |
291 | |
292 | /// Creates a new encoder for the next type in this component. |
293 | pub fn ty(&mut self) -> (u32, ComponentTypeEncoder<'_>) { |
294 | (inc(&mut self.types), self.types().ty()) |
295 | } |
296 | |
297 | /// Creates a new instance type within this component. |
298 | pub fn type_instance(&mut self, ty: &InstanceType) -> u32 { |
299 | self.types().instance(ty); |
300 | inc(&mut self.types) |
301 | } |
302 | |
303 | /// Creates a new component type within this component. |
304 | pub fn type_component(&mut self, ty: &ComponentType) -> u32 { |
305 | self.types().component(ty); |
306 | inc(&mut self.types) |
307 | } |
308 | |
309 | /// Creates a new defined component type within this component. |
310 | pub fn type_defined(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) { |
311 | (inc(&mut self.types), self.types().defined_type()) |
312 | } |
313 | |
314 | /// Creates a new component function type within this component. |
315 | pub fn type_function(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) { |
316 | (inc(&mut self.types), self.types().function()) |
317 | } |
318 | |
319 | /// Declares a |
320 | pub fn type_resource(&mut self, rep: ValType, dtor: Option<u32>) -> u32 { |
321 | self.types().resource(rep, dtor); |
322 | inc(&mut self.types) |
323 | } |
324 | |
325 | /// Defines a new subcomponent of this component. |
326 | pub fn component(&mut self, mut builder: ComponentBuilder) -> u32 { |
327 | builder.flush(); |
328 | self.flush(); |
329 | self.component |
330 | .section(&NestedComponentSection(&builder.component)); |
331 | inc(&mut self.components) |
332 | } |
333 | |
334 | /// Defines a new subcomponent of this component. |
335 | pub fn component_raw(&mut self, data: &[u8]) -> u32 { |
336 | let raw_section = RawSection { |
337 | id: ComponentSectionId::Component.into(), |
338 | data, |
339 | }; |
340 | self.flush(); |
341 | self.component.section(&raw_section); |
342 | inc(&mut self.components) |
343 | } |
344 | |
345 | /// Instantiates the `component_index` specified with the `args` specified. |
346 | pub fn instantiate<A, S>(&mut self, component_index: u32, args: A) -> u32 |
347 | where |
348 | A: IntoIterator<Item = (S, ComponentExportKind, u32)>, |
349 | A::IntoIter: ExactSizeIterator, |
350 | S: AsRef<str>, |
351 | { |
352 | self.component_instances() |
353 | .instantiate(component_index, args); |
354 | inc(&mut self.instances) |
355 | } |
356 | |
357 | /// Declares a new `resource.drop` intrinsic. |
358 | pub fn resource_drop(&mut self, ty: u32) -> u32 { |
359 | self.canonical_functions().resource_drop(ty); |
360 | inc(&mut self.core_funcs) |
361 | } |
362 | |
363 | /// Declares a new `resource.new` intrinsic. |
364 | pub fn resource_new(&mut self, ty: u32) -> u32 { |
365 | self.canonical_functions().resource_new(ty); |
366 | inc(&mut self.core_funcs) |
367 | } |
368 | |
369 | /// Declares a new `resource.rep` intrinsic. |
370 | pub fn resource_rep(&mut self, ty: u32) -> u32 { |
371 | self.canonical_functions().resource_rep(ty); |
372 | inc(&mut self.core_funcs) |
373 | } |
374 | |
375 | /// Declares a new `thread.spawn` intrinsic. |
376 | pub fn thread_spawn(&mut self, ty: u32) -> u32 { |
377 | self.canonical_functions().thread_spawn(ty); |
378 | inc(&mut self.core_funcs) |
379 | } |
380 | |
381 | /// Declares a new `thread.hw_concurrency` intrinsic. |
382 | pub fn thread_hw_concurrency(&mut self) -> u32 { |
383 | self.canonical_functions().thread_hw_concurrency(); |
384 | inc(&mut self.core_funcs) |
385 | } |
386 | |
387 | /// Adds a new custom section to this component. |
388 | pub fn custom_section(&mut self, section: &CustomSection<'_>) { |
389 | self.flush(); |
390 | self.component.section(section); |
391 | } |
392 | |
393 | /// Adds a new custom section to this component. |
394 | pub fn raw_custom_section(&mut self, section: &[u8]) { |
395 | self.flush(); |
396 | self.component.section(&RawCustomSection(section)); |
397 | } |
398 | } |
399 | |
400 | // Helper macro to generate methods on `ComponentBuilder` to get specific |
401 | // section encoders that automatically flush and write out prior sections as |
402 | // necessary. |
403 | macro_rules! section_accessors { |
404 | ($($method:ident => $section:ident)*) => ( |
405 | #[derive(Debug, Default)] |
406 | enum LastSection { |
407 | #[default] |
408 | None, |
409 | $($section($section),)* |
410 | } |
411 | |
412 | impl ComponentBuilder { |
413 | $( |
414 | fn $method(&mut self) -> &mut $section { |
415 | match &self.last_section { |
416 | // The last encoded section matches the section that's |
417 | // being requested, so no change is necessary. |
418 | LastSection::$section(_) => {} |
419 | |
420 | // Otherwise the last section didn't match this section, |
421 | // so flush any prior section if needed and start |
422 | // encoding the desired section of this method. |
423 | _ => { |
424 | self.flush(); |
425 | self.last_section = LastSection::$section($section::new()); |
426 | } |
427 | } |
428 | match &mut self.last_section { |
429 | LastSection::$section(ret) => ret, |
430 | _ => unreachable!() |
431 | } |
432 | } |
433 | )* |
434 | |
435 | /// Writes out the last section into the final component binary if |
436 | /// there is a section specified, otherwise does nothing. |
437 | fn flush(&mut self) { |
438 | match mem::take(&mut self.last_section) { |
439 | LastSection::None => {} |
440 | $( |
441 | LastSection::$section(section) => { |
442 | self.component.section(§ion); |
443 | } |
444 | )* |
445 | } |
446 | } |
447 | |
448 | } |
449 | ) |
450 | } |
451 | |
452 | section_accessors! { |
453 | component_instances => ComponentInstanceSection |
454 | instances => InstanceSection |
455 | canonical_functions => CanonicalFunctionSection |
456 | aliases => ComponentAliasSection |
457 | exports => ComponentExportSection |
458 | imports => ComponentImportSection |
459 | types => ComponentTypeSection |
460 | core_types => CoreTypeSection |
461 | } |
462 | |
463 | fn inc(idx: &mut u32) -> u32 { |
464 | let ret: u32 = *idx; |
465 | *idx += 1; |
466 | ret |
467 | } |
468 | |