1use crate::component::*;
2use crate::{ExportKind, Module, RawSection, ValType};
3use 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)]
13pub 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
43impl 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.
403macro_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(&section);
443 }
444 )*
445 }
446 }
447
448 }
449 )
450}
451
452section_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
463fn inc(idx: &mut u32) -> u32 {
464 let ret: u32 = *idx;
465 *idx += 1;
466 ret
467}
468