1use crate::component::*;
2use crate::{ExportKind, Module, RawSection, ValType};
3use alloc::vec::Vec;
4use core::mem;
5
6/// Convenience type to build a component incrementally and automatically keep
7/// track of index spaces.
8///
9/// This type is intended to be a wrapper around the [`Component`] encoding type
10/// which is useful for building it up incrementally over time. This type will
11/// automatically collect definitions into sections and reports the index of all
12/// items added by keeping track of indices internally.
13#[derive(Debug, Default)]
14pub struct ComponentBuilder {
15 /// The binary component that's being built.
16 component: Component,
17
18 /// The last section which was appended to during encoding. This type is
19 /// generated by the `section_accessors` macro below.
20 ///
21 /// When something is encoded this is used if it matches the kind of item
22 /// being encoded, otherwise it's "flushed" to the output component and a
23 /// new section is started.
24 last_section: LastSection,
25
26 // Core index spaces
27 core_modules: u32,
28 core_funcs: u32,
29 core_types: u32,
30 core_memories: u32,
31 core_tables: u32,
32 core_instances: u32,
33 core_tags: u32,
34 core_globals: u32,
35
36 // Component index spaces
37 funcs: u32,
38 instances: u32,
39 types: u32,
40 components: u32,
41 values: u32,
42}
43
44impl ComponentBuilder {
45 /// Returns the current number of core modules.
46 pub fn core_module_count(&self) -> u32 {
47 self.core_modules
48 }
49
50 /// Returns the current number of core funcs.
51 pub fn core_func_count(&self) -> u32 {
52 self.core_funcs
53 }
54
55 /// Returns the current number of core types.
56 pub fn core_type_count(&self) -> u32 {
57 self.core_types
58 }
59
60 /// Returns the current number of core memories.
61 pub fn core_memory_count(&self) -> u32 {
62 self.core_memories
63 }
64
65 /// Returns the current number of core tables.
66 pub fn core_table_count(&self) -> u32 {
67 self.core_tables
68 }
69
70 /// Returns the current number of core instances.
71 pub fn core_instance_count(&self) -> u32 {
72 self.core_instances
73 }
74
75 /// Returns the current number of core tags.
76 pub fn core_tag_count(&self) -> u32 {
77 self.core_tags
78 }
79
80 /// Returns the current number of core globals.
81 pub fn core_global_count(&self) -> u32 {
82 self.core_globals
83 }
84
85 /// Returns the current number of component funcs.
86 pub fn func_count(&self) -> u32 {
87 self.funcs
88 }
89
90 /// Returns the current number of component instances.
91 pub fn instance_count(&self) -> u32 {
92 self.instances
93 }
94
95 /// Returns the current number of component values.
96 pub fn value_count(&self) -> u32 {
97 self.values
98 }
99
100 /// Returns the current number of components.
101 pub fn component_count(&self) -> u32 {
102 self.components
103 }
104
105 /// Returns the current number of component types.
106 pub fn type_count(&self) -> u32 {
107 self.types
108 }
109
110 /// Completes this component and returns the binary encoding of the entire
111 /// component.
112 pub fn finish(mut self) -> Vec<u8> {
113 self.flush();
114 self.component.finish()
115 }
116
117 /// Encodes a core wasm `Module` into this component, returning its index.
118 pub fn core_module(&mut self, module: &Module) -> u32 {
119 self.flush();
120 self.component.section(&ModuleSection(module));
121 inc(&mut self.core_modules)
122 }
123
124 /// Encodes a core wasm `module` into this component, returning its index.
125 pub fn core_module_raw(&mut self, module: &[u8]) -> u32 {
126 self.flush();
127 self.component.section(&RawSection {
128 id: ComponentSectionId::CoreModule.into(),
129 data: module,
130 });
131 inc(&mut self.core_modules)
132 }
133
134 /// Instantiates a core wasm module at `module_index` with the `args`
135 /// provided.
136 ///
137 /// Returns the index of the core wasm instance crated.
138 pub fn core_instantiate<'a, A>(&mut self, module_index: u32, args: A) -> u32
139 where
140 A: IntoIterator<Item = (&'a str, ModuleArg)>,
141 A::IntoIter: ExactSizeIterator,
142 {
143 self.instances().instantiate(module_index, args);
144 inc(&mut self.core_instances)
145 }
146
147 /// Creates a new core wasm instance from the `exports` provided.
148 ///
149 /// Returns the index of the core wasm instance crated.
150 pub fn core_instantiate_exports<'a, E>(&mut self, exports: E) -> u32
151 where
152 E: IntoIterator<Item = (&'a str, ExportKind, u32)>,
153 E::IntoIter: ExactSizeIterator,
154 {
155 self.instances().export_items(exports);
156 inc(&mut self.core_instances)
157 }
158
159 /// Creates a new aliased item where the core `instance` specified has its
160 /// export `name` aliased out with the `kind` specified.
161 ///
162 /// Returns the index of the item crated.
163 pub fn core_alias_export(&mut self, instance: u32, name: &str, kind: ExportKind) -> u32 {
164 self.alias(Alias::CoreInstanceExport {
165 instance,
166 kind,
167 name,
168 })
169 }
170
171 /// Adds a new alias to this component
172 pub fn alias(&mut self, alias: Alias<'_>) -> u32 {
173 self.aliases().alias(alias);
174 match alias {
175 Alias::InstanceExport { kind, .. } => self.inc_kind(kind),
176 Alias::CoreInstanceExport { kind, .. } => self.inc_core_kind(kind),
177 Alias::Outer {
178 kind: ComponentOuterAliasKind::Type,
179 ..
180 } => inc(&mut self.types),
181 Alias::Outer {
182 kind: ComponentOuterAliasKind::CoreModule,
183 ..
184 } => inc(&mut self.core_modules),
185 Alias::Outer {
186 kind: ComponentOuterAliasKind::Component,
187 ..
188 } => inc(&mut self.components),
189 Alias::Outer {
190 kind: ComponentOuterAliasKind::CoreType,
191 ..
192 } => inc(&mut self.core_types),
193 }
194 }
195
196 /// Creates an alias to a previous component instance's exported item.
197 ///
198 /// The `instance` provided is the instance to access and the `name` is the
199 /// item to access.
200 ///
201 /// Returns the index of the new item defined.
202 pub fn alias_export(&mut self, instance: u32, name: &str, kind: ComponentExportKind) -> u32 {
203 self.alias(Alias::InstanceExport {
204 instance,
205 kind,
206 name,
207 })
208 }
209
210 fn inc_kind(&mut self, kind: ComponentExportKind) -> u32 {
211 match kind {
212 ComponentExportKind::Func => inc(&mut self.funcs),
213 ComponentExportKind::Module => inc(&mut self.core_modules),
214 ComponentExportKind::Type => inc(&mut self.types),
215 ComponentExportKind::Component => inc(&mut self.components),
216 ComponentExportKind::Instance => inc(&mut self.instances),
217 ComponentExportKind::Value => inc(&mut self.values),
218 }
219 }
220
221 fn inc_core_kind(&mut self, kind: ExportKind) -> u32 {
222 match kind {
223 ExportKind::Func => inc(&mut self.core_funcs),
224 ExportKind::Table => inc(&mut self.core_tables),
225 ExportKind::Memory => inc(&mut self.core_memories),
226 ExportKind::Global => inc(&mut self.core_globals),
227 ExportKind::Tag => inc(&mut self.core_tags),
228 }
229 }
230
231 /// Lowers the `func_index` component function into a core wasm function
232 /// using the `options` provided.
233 ///
234 /// Returns the index of the core wasm function created.
235 pub fn lower_func<O>(&mut self, func_index: u32, options: O) -> u32
236 where
237 O: IntoIterator<Item = CanonicalOption>,
238 O::IntoIter: ExactSizeIterator,
239 {
240 self.canonical_functions().lower(func_index, options);
241 inc(&mut self.core_funcs)
242 }
243
244 /// Lifts the core wasm `core_func_index` function with the component
245 /// function type `type_index` and `options`.
246 ///
247 /// Returns the index of the component function created.
248 pub fn lift_func<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> u32
249 where
250 O: IntoIterator<Item = CanonicalOption>,
251 O::IntoIter: ExactSizeIterator,
252 {
253 self.canonical_functions()
254 .lift(core_func_index, type_index, options);
255 inc(&mut self.funcs)
256 }
257
258 /// Imports a new item into this component with the `name` and `ty` specified.
259 pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> u32 {
260 let ret = match &ty {
261 ComponentTypeRef::Instance(_) => inc(&mut self.instances),
262 ComponentTypeRef::Func(_) => inc(&mut self.funcs),
263 ComponentTypeRef::Type(..) => inc(&mut self.types),
264 ComponentTypeRef::Component(_) => inc(&mut self.components),
265 ComponentTypeRef::Module(_) => inc(&mut self.core_modules),
266 ComponentTypeRef::Value(_) => inc(&mut self.values),
267 };
268 self.imports().import(name, ty);
269 ret
270 }
271
272 /// Exports a new item from this component with the `name` and `kind`
273 /// specified.
274 ///
275 /// The `idx` is the item to export and the `ty` is an optional type to
276 /// ascribe to the export.
277 pub fn export(
278 &mut self,
279 name: &str,
280 kind: ComponentExportKind,
281 idx: u32,
282 ty: Option<ComponentTypeRef>,
283 ) -> u32 {
284 self.exports().export(name, kind, idx, ty);
285 self.inc_kind(kind)
286 }
287
288 /// Creates a new encoder for the next core type in this component.
289 pub fn core_type(&mut self) -> (u32, ComponentCoreTypeEncoder<'_>) {
290 (inc(&mut self.core_types), self.core_types().ty())
291 }
292
293 /// Creates a new encoder for the next type in this component.
294 pub fn ty(&mut self) -> (u32, ComponentTypeEncoder<'_>) {
295 (inc(&mut self.types), self.types().ty())
296 }
297
298 /// Creates a new instance type within this component.
299 pub fn type_instance(&mut self, ty: &InstanceType) -> u32 {
300 self.types().instance(ty);
301 inc(&mut self.types)
302 }
303
304 /// Creates a new component type within this component.
305 pub fn type_component(&mut self, ty: &ComponentType) -> u32 {
306 self.types().component(ty);
307 inc(&mut self.types)
308 }
309
310 /// Creates a new defined component type within this component.
311 pub fn type_defined(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
312 (inc(&mut self.types), self.types().defined_type())
313 }
314
315 /// Creates a new component function type within this component.
316 pub fn type_function(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
317 (inc(&mut self.types), self.types().function())
318 }
319
320 /// Declares a new resource type within this component.
321 pub fn type_resource(&mut self, rep: ValType, dtor: Option<u32>) -> u32 {
322 self.types().resource(rep, dtor);
323 inc(&mut self.types)
324 }
325
326 /// Defines a new subcomponent of this component.
327 pub fn component(&mut self, mut builder: ComponentBuilder) -> u32 {
328 builder.flush();
329 self.flush();
330 self.component
331 .section(&NestedComponentSection(&builder.component));
332 inc(&mut self.components)
333 }
334
335 /// Defines a new subcomponent of this component.
336 pub fn component_raw(&mut self, data: &[u8]) -> u32 {
337 let raw_section = RawSection {
338 id: ComponentSectionId::Component.into(),
339 data,
340 };
341 self.flush();
342 self.component.section(&raw_section);
343 inc(&mut self.components)
344 }
345
346 /// Instantiates the `component_index` specified with the `args` specified.
347 pub fn instantiate<A, S>(&mut self, component_index: u32, args: A) -> u32
348 where
349 A: IntoIterator<Item = (S, ComponentExportKind, u32)>,
350 A::IntoIter: ExactSizeIterator,
351 S: AsRef<str>,
352 {
353 self.component_instances()
354 .instantiate(component_index, args);
355 inc(&mut self.instances)
356 }
357
358 /// Declares a new `resource.drop` intrinsic.
359 pub fn resource_drop(&mut self, ty: u32) -> u32 {
360 self.canonical_functions().resource_drop(ty);
361 inc(&mut self.core_funcs)
362 }
363
364 /// Declares a new `resource.new` intrinsic.
365 pub fn resource_new(&mut self, ty: u32) -> u32 {
366 self.canonical_functions().resource_new(ty);
367 inc(&mut self.core_funcs)
368 }
369
370 /// Declares a new `resource.rep` intrinsic.
371 pub fn resource_rep(&mut self, ty: u32) -> u32 {
372 self.canonical_functions().resource_rep(ty);
373 inc(&mut self.core_funcs)
374 }
375
376 /// Declares a new `thread.spawn` intrinsic.
377 pub fn thread_spawn(&mut self, ty: u32) -> u32 {
378 self.canonical_functions().thread_spawn(ty);
379 inc(&mut self.core_funcs)
380 }
381
382 /// Declares a new `thread.hw_concurrency` intrinsic.
383 pub fn thread_hw_concurrency(&mut self) -> u32 {
384 self.canonical_functions().thread_hw_concurrency();
385 inc(&mut self.core_funcs)
386 }
387
388 /// Declares a new `task.backpressure` intrinsic.
389 pub fn task_backpressure(&mut self) -> u32 {
390 self.canonical_functions().task_backpressure();
391 inc(&mut self.core_funcs)
392 }
393
394 /// Declares a new `task.return` intrinsic.
395 pub fn task_return(&mut self, ty: u32) -> u32 {
396 self.canonical_functions().task_return(ty);
397 inc(&mut self.core_funcs)
398 }
399
400 /// Declares a new `task.wait` intrinsic.
401 pub fn task_wait(&mut self, async_: bool, memory: u32) -> u32 {
402 self.canonical_functions().task_wait(async_, memory);
403 inc(&mut self.core_funcs)
404 }
405
406 /// Declares a new `task.poll` intrinsic.
407 pub fn task_poll(&mut self, async_: bool, memory: u32) -> u32 {
408 self.canonical_functions().task_poll(async_, memory);
409 inc(&mut self.core_funcs)
410 }
411
412 /// Declares a new `task.yield` intrinsic.
413 pub fn task_yield(&mut self, async_: bool) -> u32 {
414 self.canonical_functions().task_yield(async_);
415 inc(&mut self.core_funcs)
416 }
417
418 /// Declares a new `subtask.drop` intrinsic.
419 pub fn subtask_drop(&mut self) -> u32 {
420 self.canonical_functions().subtask_drop();
421 inc(&mut self.core_funcs)
422 }
423
424 /// Declares a new `stream.new` intrinsic.
425 pub fn stream_new(&mut self, ty: u32) -> u32 {
426 self.canonical_functions().stream_new(ty);
427 inc(&mut self.core_funcs)
428 }
429
430 /// Declares a new `stream.read` intrinsic.
431 pub fn stream_read<O>(&mut self, ty: u32, options: O) -> u32
432 where
433 O: IntoIterator<Item = CanonicalOption>,
434 O::IntoIter: ExactSizeIterator,
435 {
436 self.canonical_functions().stream_read(ty, options);
437 inc(&mut self.core_funcs)
438 }
439
440 /// Declares a new `stream.write` intrinsic.
441 pub fn stream_write<O>(&mut self, ty: u32, options: O) -> u32
442 where
443 O: IntoIterator<Item = CanonicalOption>,
444 O::IntoIter: ExactSizeIterator,
445 {
446 self.canonical_functions().stream_write(ty, options);
447 inc(&mut self.core_funcs)
448 }
449
450 /// Declares a new `stream.cancel-read` intrinsic.
451 pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> u32 {
452 self.canonical_functions().stream_cancel_read(ty, async_);
453 inc(&mut self.core_funcs)
454 }
455
456 /// Declares a new `stream.cancel-write` intrinsic.
457 pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> u32 {
458 self.canonical_functions().stream_cancel_write(ty, async_);
459 inc(&mut self.core_funcs)
460 }
461
462 /// Declares a new `stream.close-readable` intrinsic.
463 pub fn stream_close_readable(&mut self, ty: u32) -> u32 {
464 self.canonical_functions().stream_close_readable(ty);
465 inc(&mut self.core_funcs)
466 }
467
468 /// Declares a new `stream.close-writable` intrinsic.
469 pub fn stream_close_writable(&mut self, ty: u32) -> u32 {
470 self.canonical_functions().stream_close_writable(ty);
471 inc(&mut self.core_funcs)
472 }
473
474 /// Declares a new `future.new` intrinsic.
475 pub fn future_new(&mut self, ty: u32) -> u32 {
476 self.canonical_functions().future_new(ty);
477 inc(&mut self.core_funcs)
478 }
479
480 /// Declares a new `future.read` intrinsic.
481 pub fn future_read<O>(&mut self, ty: u32, options: O) -> u32
482 where
483 O: IntoIterator<Item = CanonicalOption>,
484 O::IntoIter: ExactSizeIterator,
485 {
486 self.canonical_functions().future_read(ty, options);
487 inc(&mut self.core_funcs)
488 }
489
490 /// Declares a new `future.write` intrinsic.
491 pub fn future_write<O>(&mut self, ty: u32, options: O) -> u32
492 where
493 O: IntoIterator<Item = CanonicalOption>,
494 O::IntoIter: ExactSizeIterator,
495 {
496 self.canonical_functions().future_write(ty, options);
497 inc(&mut self.core_funcs)
498 }
499
500 /// Declares a new `future.cancel-read` intrinsic.
501 pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> u32 {
502 self.canonical_functions().future_cancel_read(ty, async_);
503 inc(&mut self.core_funcs)
504 }
505
506 /// Declares a new `future.cancel-write` intrinsic.
507 pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> u32 {
508 self.canonical_functions().future_cancel_write(ty, async_);
509 inc(&mut self.core_funcs)
510 }
511
512 /// Declares a new `future.close-readable` intrinsic.
513 pub fn future_close_readable(&mut self, ty: u32) -> u32 {
514 self.canonical_functions().future_close_readable(ty);
515 inc(&mut self.core_funcs)
516 }
517
518 /// Declares a new `future.close-writable` intrinsic.
519 pub fn future_close_writable(&mut self, ty: u32) -> u32 {
520 self.canonical_functions().future_close_writable(ty);
521 inc(&mut self.core_funcs)
522 }
523
524 /// Declares a new `error-context.new` intrinsic.
525 pub fn error_context_new<O>(&mut self, options: O) -> u32
526 where
527 O: IntoIterator<Item = CanonicalOption>,
528 O::IntoIter: ExactSizeIterator,
529 {
530 self.canonical_functions().error_context_new(options);
531 inc(&mut self.core_funcs)
532 }
533
534 /// Declares a new `error-context.debug-message` intrinsic.
535 pub fn error_context_debug_message<O>(&mut self, options: O) -> u32
536 where
537 O: IntoIterator<Item = CanonicalOption>,
538 O::IntoIter: ExactSizeIterator,
539 {
540 self.canonical_functions()
541 .error_context_debug_message(options);
542 inc(&mut self.core_funcs)
543 }
544
545 /// Declares a new `error-context.drop` intrinsic.
546 pub fn error_context_drop(&mut self) -> u32 {
547 self.canonical_functions().error_context_drop();
548 inc(&mut self.core_funcs)
549 }
550
551 /// Adds a new custom section to this component.
552 pub fn custom_section(&mut self, section: &CustomSection<'_>) {
553 self.flush();
554 self.component.section(section);
555 }
556
557 /// Adds a new custom section to this component.
558 pub fn raw_custom_section(&mut self, section: &[u8]) {
559 self.flush();
560 self.component.section(&RawCustomSection(section));
561 }
562}
563
564// Helper macro to generate methods on `ComponentBuilder` to get specific
565// section encoders that automatically flush and write out prior sections as
566// necessary.
567macro_rules! section_accessors {
568 ($($method:ident => $section:ident)*) => (
569 #[derive(Debug, Default)]
570 enum LastSection {
571 #[default]
572 None,
573 $($section($section),)*
574 }
575
576 impl ComponentBuilder {
577 $(
578 fn $method(&mut self) -> &mut $section {
579 match &self.last_section {
580 // The last encoded section matches the section that's
581 // being requested, so no change is necessary.
582 LastSection::$section(_) => {}
583
584 // Otherwise the last section didn't match this section,
585 // so flush any prior section if needed and start
586 // encoding the desired section of this method.
587 _ => {
588 self.flush();
589 self.last_section = LastSection::$section($section::new());
590 }
591 }
592 match &mut self.last_section {
593 LastSection::$section(ret) => ret,
594 _ => unreachable!()
595 }
596 }
597 )*
598
599 /// Writes out the last section into the final component binary if
600 /// there is a section specified, otherwise does nothing.
601 fn flush(&mut self) {
602 match mem::take(&mut self.last_section) {
603 LastSection::None => {}
604 $(
605 LastSection::$section(section) => {
606 self.component.section(&section);
607 }
608 )*
609 }
610 }
611
612 }
613 )
614}
615
616section_accessors! {
617 component_instances => ComponentInstanceSection
618 instances => InstanceSection
619 canonical_functions => CanonicalFunctionSection
620 aliases => ComponentAliasSection
621 exports => ComponentExportSection
622 imports => ComponentImportSection
623 types => ComponentTypeSection
624 core_types => CoreTypeSection
625}
626
627fn inc(idx: &mut u32) -> u32 {
628 let ret: u32 = *idx;
629 *idx += 1;
630 ret
631}
632