Skip to main content

wasm_encoder/component/
builder.rs

1use crate::component::*;
2use crate::{ExportKind, Module, NameMap, RawSection, ValType};
3use alloc::format;
4use alloc::vec::Vec;
5use core::mem;
6
7/// Convenience type to build a component incrementally and automatically keep
8/// track of index spaces.
9///
10/// This type is intended to be a wrapper around the [`Component`] encoding type
11/// which is useful for building it up incrementally over time. This type will
12/// automatically collect definitions into sections and reports the index of all
13/// items added by keeping track of indices internally.
14#[derive(Debug, Default)]
15pub struct ComponentBuilder {
16    /// The binary component that's being built.
17    component: Component,
18
19    /// The last section which was appended to during encoding. This type is
20    /// generated by the `section_accessors` macro below.
21    ///
22    /// When something is encoded this is used if it matches the kind of item
23    /// being encoded, otherwise it's "flushed" to the output component and a
24    /// new section is started.
25    last_section: LastSection,
26
27    // Core index spaces
28    core_modules: Namespace,
29    core_funcs: Namespace,
30    core_types: Namespace,
31    core_memories: Namespace,
32    core_tables: Namespace,
33    core_instances: Namespace,
34    core_tags: Namespace,
35    core_globals: Namespace,
36
37    // Component index spaces
38    funcs: Namespace,
39    instances: Namespace,
40    types: Namespace,
41    components: Namespace,
42    values: Namespace,
43}
44
45impl ComponentBuilder {
46    /// Returns the current number of core modules.
47    pub fn core_module_count(&self) -> u32 {
48        self.core_modules.count
49    }
50
51    /// Returns the current number of core funcs.
52    pub fn core_func_count(&self) -> u32 {
53        self.core_funcs.count
54    }
55
56    /// Returns the current number of core types.
57    pub fn core_type_count(&self) -> u32 {
58        self.core_types.count
59    }
60
61    /// Returns the current number of core memories.
62    pub fn core_memory_count(&self) -> u32 {
63        self.core_memories.count
64    }
65
66    /// Returns the current number of core tables.
67    pub fn core_table_count(&self) -> u32 {
68        self.core_tables.count
69    }
70
71    /// Returns the current number of core instances.
72    pub fn core_instance_count(&self) -> u32 {
73        self.core_instances.count
74    }
75
76    /// Returns the current number of core tags.
77    pub fn core_tag_count(&self) -> u32 {
78        self.core_tags.count
79    }
80
81    /// Returns the current number of core globals.
82    pub fn core_global_count(&self) -> u32 {
83        self.core_globals.count
84    }
85
86    /// Returns the current number of component funcs.
87    pub fn func_count(&self) -> u32 {
88        self.funcs.count
89    }
90
91    /// Returns the current number of component instances.
92    pub fn instance_count(&self) -> u32 {
93        self.instances.count
94    }
95
96    /// Returns the current number of component values.
97    pub fn value_count(&self) -> u32 {
98        self.values.count
99    }
100
101    /// Returns the current number of components.
102    pub fn component_count(&self) -> u32 {
103        self.components.count
104    }
105
106    /// Returns the current number of component types.
107    pub fn type_count(&self) -> u32 {
108        self.types.count
109    }
110
111    /// Add all debug names registered to the component.
112    pub fn append_names(&mut self) {
113        let mut names = ComponentNameSection::new();
114        if !self.core_funcs.names.is_empty() {
115            names.core_funcs(&self.core_funcs.names);
116        }
117        if !self.core_tables.names.is_empty() {
118            names.core_tables(&self.core_tables.names);
119        }
120        if !self.core_memories.names.is_empty() {
121            names.core_memories(&self.core_memories.names);
122        }
123        if !self.core_globals.names.is_empty() {
124            names.core_globals(&self.core_globals.names);
125        }
126        if !self.core_tags.names.is_empty() {
127            names.core_tags(&self.core_tags.names);
128        }
129        if !self.core_types.names.is_empty() {
130            names.core_types(&self.core_types.names);
131        }
132        if !self.core_modules.names.is_empty() {
133            names.core_modules(&self.core_modules.names);
134        }
135        if !self.core_instances.names.is_empty() {
136            names.core_instances(&self.core_instances.names);
137        }
138        if !self.instances.names.is_empty() {
139            names.instances(&self.instances.names);
140        }
141        if !self.funcs.names.is_empty() {
142            names.funcs(&self.funcs.names);
143        }
144        if !self.types.names.is_empty() {
145            names.types(&self.types.names);
146        }
147        if !self.components.names.is_empty() {
148            names.components(&self.components.names);
149        }
150        if !self.instances.names.is_empty() {
151            names.instances(&self.instances.names);
152        }
153        if !names.is_empty() {
154            self.custom_section(&names.as_custom());
155        }
156    }
157
158    /// Completes this component and returns the binary encoding of the entire
159    /// component.
160    pub fn finish(mut self) -> Vec<u8> {
161        self.flush();
162        self.component.finish()
163    }
164
165    /// Encodes a core wasm `Module` into this component, returning its index.
166    pub fn core_module(&mut self, debug_name: Option<&str>, module: &Module) -> u32 {
167        self.flush();
168        self.component.section(&ModuleSection(module));
169        self.core_modules.add(debug_name)
170    }
171
172    /// Encodes a core wasm `module` into this component, returning its index.
173    pub fn core_module_raw(&mut self, debug_name: Option<&str>, module: &[u8]) -> u32 {
174        self.flush();
175        self.component.section(&RawSection {
176            id: ComponentSectionId::CoreModule.into(),
177            data: module,
178        });
179        self.core_modules.add(debug_name)
180    }
181
182    /// Instantiates a core wasm module at `module_index` with the `args`
183    /// provided.
184    ///
185    /// Returns the index of the core wasm instance created.
186    pub fn core_instantiate<'a, A>(
187        &mut self,
188        debug_name: Option<&str>,
189        module_index: u32,
190        args: A,
191    ) -> u32
192    where
193        A: IntoIterator<Item = (&'a str, ModuleArg)>,
194        A::IntoIter: ExactSizeIterator,
195    {
196        self.instances().instantiate(module_index, args);
197        self.core_instances.add(debug_name)
198    }
199
200    /// Creates a new core wasm instance from the `exports` provided.
201    ///
202    /// Returns the index of the core wasm instance created.
203    pub fn core_instantiate_exports<'a, E>(&mut self, debug_name: Option<&str>, exports: E) -> u32
204    where
205        E: IntoIterator<Item = (&'a str, ExportKind, u32)>,
206        E::IntoIter: ExactSizeIterator,
207    {
208        self.instances().export_items(exports);
209        self.core_instances.add(debug_name)
210    }
211
212    /// Creates a new aliased item where the core `instance` specified has its
213    /// export `name` aliased out with the `kind` specified.
214    ///
215    /// Returns the index of the item created.
216    pub fn core_alias_export(
217        &mut self,
218        debug_name: Option<&str>,
219        instance: u32,
220        name: &str,
221        kind: ExportKind,
222    ) -> u32 {
223        self.alias(
224            debug_name,
225            Alias::CoreInstanceExport {
226                instance,
227                kind,
228                name,
229            },
230        )
231    }
232
233    /// Adds a new alias to this component
234    pub fn alias(&mut self, debug_name: Option<&str>, alias: Alias<'_>) -> u32 {
235        self.aliases().alias(alias);
236        match alias {
237            Alias::InstanceExport { kind, .. } => self.inc_kind(debug_name, kind),
238            Alias::CoreInstanceExport { kind, .. } => self.inc_core_kind(debug_name, kind),
239            Alias::Outer {
240                kind: ComponentOuterAliasKind::Type,
241                ..
242            } => self.types.add(debug_name),
243            Alias::Outer {
244                kind: ComponentOuterAliasKind::CoreModule,
245                ..
246            } => self.core_modules.add(debug_name),
247            Alias::Outer {
248                kind: ComponentOuterAliasKind::Component,
249                ..
250            } => self.components.add(debug_name),
251            Alias::Outer {
252                kind: ComponentOuterAliasKind::CoreType,
253                ..
254            } => self.core_types.add(debug_name),
255        }
256    }
257
258    /// Creates an alias to a previous component instance's exported item.
259    ///
260    /// The `instance` provided is the instance to access and the `name` is the
261    /// item to access.
262    ///
263    /// Returns the index of the new item defined.
264    pub fn alias_export(&mut self, instance: u32, name: &str, kind: ComponentExportKind) -> u32 {
265        self.alias(
266            Some(name),
267            Alias::InstanceExport {
268                instance,
269                kind,
270                name,
271            },
272        )
273    }
274
275    fn inc_kind(&mut self, debug_name: Option<&str>, kind: ComponentExportKind) -> u32 {
276        match kind {
277            ComponentExportKind::Func => self.funcs.add(debug_name),
278            ComponentExportKind::Module => self.core_modules.add(debug_name),
279            ComponentExportKind::Type => self.types.add(debug_name),
280            ComponentExportKind::Component => self.components.add(debug_name),
281            ComponentExportKind::Instance => self.instances.add(debug_name),
282            ComponentExportKind::Value => self.values.add(debug_name),
283        }
284    }
285
286    fn inc_core_kind(&mut self, debug_name: Option<&str>, kind: ExportKind) -> u32 {
287        match kind {
288            ExportKind::Func => self.core_funcs.add(debug_name),
289            ExportKind::Table => self.core_tables.add(debug_name),
290            ExportKind::Memory => self.core_memories.add(debug_name),
291            ExportKind::Global => self.core_globals.add(debug_name),
292            ExportKind::Tag => self.core_tags.add(debug_name),
293        }
294    }
295
296    /// Lowers the `func_index` component function into a core wasm function
297    /// using the `options` provided.
298    ///
299    /// Returns the index of the core wasm function created.
300    pub fn lower_func<O>(&mut self, debug_name: Option<&str>, func_index: u32, options: O) -> u32
301    where
302        O: IntoIterator<Item = CanonicalOption>,
303        O::IntoIter: ExactSizeIterator,
304    {
305        self.canonical_functions().lower(func_index, options);
306        self.core_funcs.add(debug_name)
307    }
308
309    /// Lifts the core wasm `core_func_index` function with the component
310    /// function type `type_index` and `options`.
311    ///
312    /// Returns the index of the component function created.
313    pub fn lift_func<O>(
314        &mut self,
315        debug_name: Option<&str>,
316        core_func_index: u32,
317        type_index: u32,
318        options: O,
319    ) -> u32
320    where
321        O: IntoIterator<Item = CanonicalOption>,
322        O::IntoIter: ExactSizeIterator,
323    {
324        self.canonical_functions()
325            .lift(core_func_index, type_index, options);
326        self.funcs.add(debug_name)
327    }
328
329    /// Imports a new item into this component with the `name` and `ty` specified.
330    pub fn import<'a>(
331        &mut self,
332        name: impl Into<ComponentExternName<'a>>,
333        ty: ComponentTypeRef,
334    ) -> u32 {
335        let name = name.into();
336        let ret = match &ty {
337            ComponentTypeRef::Instance(_) => self.instances.add(Some(&name.name)),
338            ComponentTypeRef::Func(_) => self.funcs.add(Some(&name.name)),
339            ComponentTypeRef::Type(..) => self.types.add(Some(&name.name)),
340            ComponentTypeRef::Component(_) => self.components.add(Some(&name.name)),
341            ComponentTypeRef::Module(_) => self.core_modules.add(Some(&name.name)),
342            ComponentTypeRef::Value(_) => self.values.add(Some(&name.name)),
343        };
344        self.imports().import(name, ty);
345        ret
346    }
347
348    /// Exports a new item from this component with the `name` and `kind`
349    /// specified.
350    ///
351    /// The `idx` is the item to export and the `ty` is an optional type to
352    /// ascribe to the export.
353    pub fn export<'a>(
354        &mut self,
355        name: impl Into<ComponentExternName<'a>>,
356        kind: ComponentExportKind,
357        idx: u32,
358        ty: Option<ComponentTypeRef>,
359    ) -> u32 {
360        let name = name.into();
361        self.exports().export(name.clone(), kind, idx, ty);
362        self.inc_kind(Some(&name.name), kind)
363    }
364
365    /// Creates a new encoder for the next core type in this component.
366    pub fn core_type(&mut self, debug_name: Option<&str>) -> (u32, ComponentCoreTypeEncoder<'_>) {
367        (self.core_types.add(debug_name), self.core_types().ty())
368    }
369
370    /// Creates a new encoder for the next type in this component.
371    pub fn ty(&mut self, debug_name: Option<&str>) -> (u32, ComponentTypeEncoder<'_>) {
372        (self.types.add(debug_name), self.types().ty())
373    }
374
375    /// Creates a new instance type within this component.
376    pub fn type_instance(&mut self, debug_name: Option<&str>, ty: &InstanceType) -> u32 {
377        self.types().instance(ty);
378        self.types.add(debug_name)
379    }
380
381    /// Creates a new component type within this component.
382    pub fn type_component(&mut self, debug_name: Option<&str>, ty: &ComponentType) -> u32 {
383        self.types().component(ty);
384        self.types.add(debug_name)
385    }
386
387    /// Creates a new defined component type within this component.
388    pub fn type_defined(
389        &mut self,
390        debug_name: Option<&str>,
391    ) -> (u32, ComponentDefinedTypeEncoder<'_>) {
392        (self.types.add(debug_name), self.types().defined_type())
393    }
394
395    /// Creates a new component function type within this component.
396    pub fn type_function(
397        &mut self,
398        debug_name: Option<&str>,
399    ) -> (u32, ComponentFuncTypeEncoder<'_>) {
400        (self.types.add(debug_name), self.types().function())
401    }
402
403    /// Declares a new resource type within this component.
404    pub fn type_resource(
405        &mut self,
406        debug_name: Option<&str>,
407        rep: ValType,
408        dtor: Option<u32>,
409    ) -> u32 {
410        self.types().resource(rep, dtor);
411        self.types.add(debug_name)
412    }
413
414    /// Defines a new subcomponent of this component.
415    pub fn component(&mut self, debug_name: Option<&str>, mut builder: ComponentBuilder) -> u32 {
416        builder.flush();
417        self.flush();
418        self.component
419            .section(&NestedComponentSection(&builder.component));
420        self.components.add(debug_name)
421    }
422
423    /// Defines a new subcomponent of this component.
424    pub fn component_raw(&mut self, debug_name: Option<&str>, data: &[u8]) -> u32 {
425        let raw_section = RawSection {
426            id: ComponentSectionId::Component.into(),
427            data,
428        };
429        self.flush();
430        self.component.section(&raw_section);
431        self.components.add(debug_name)
432    }
433
434    /// Instantiates the `component_index` specified with the `args` specified.
435    pub fn instantiate<A, S>(
436        &mut self,
437        debug_name: Option<&str>,
438        component_index: u32,
439        args: A,
440    ) -> u32
441    where
442        A: IntoIterator<Item = (S, ComponentExportKind, u32)>,
443        A::IntoIter: ExactSizeIterator,
444        S: AsRef<str>,
445    {
446        self.component_instances()
447            .instantiate(component_index, args);
448        self.instances.add(debug_name)
449    }
450
451    /// Emits a component start section, invoking `function_index`
452    /// at instantiation time with `args` (each an index into the
453    /// component value index space) and producing `results` new
454    /// values.
455    ///
456    /// Returns the index of the FIRST produced value in the
457    /// component value index space (subsequent produced values
458    /// occupy `first+1`, `first+2`, …, `first+results-1`). If
459    /// `results == 0` the return value is still the current
460    /// value-index cursor but no new values are added; callers
461    /// typically ignore it in that case.
462    ///
463    /// The Component Model spec permits at most one start section
464    /// per component. This helper does NOT enforce that; passing
465    /// the responsibility to the caller matches how the underlying
466    /// `ComponentStartSection` encoder behaves.
467    pub fn start(&mut self, function_index: u32, args: Vec<u32>, results: u32) -> u32 {
468        // Component start is a singleton section rather than an
469        // aggregating one, so we don't route it through the
470        // section-accessor macro. Flush any last section first so
471        // section ordering stays coherent.
472        self.flush();
473        self.component.section(&ComponentStartSection {
474            function_index,
475            args,
476            results,
477        });
478        let base = self.values.count;
479        for _ in 0..results {
480            self.values.add(None);
481        }
482        base
483    }
484
485    /// Creates a new component instance from the `exports` provided.
486    ///
487    /// Returns the index of the component instance created.
488    pub fn instantiate_exports<'a, E, N>(&mut self, debug_name: Option<&str>, exports: E) -> u32
489    where
490        E: IntoIterator<Item = (N, ComponentExportKind, u32)>,
491        E::IntoIter: ExactSizeIterator,
492        N: Into<ComponentExternName<'a>>,
493    {
494        self.component_instances().export_items(exports);
495        self.instances.add(debug_name)
496    }
497
498    /// Declares a new `resource.drop` intrinsic.
499    pub fn resource_drop(&mut self, ty: u32) -> u32 {
500        self.canonical_functions().resource_drop(ty);
501        self.core_funcs.add(Some("resource.drop"))
502    }
503
504    /// Declares a new `resource.new` intrinsic.
505    pub fn resource_new(&mut self, ty: u32) -> u32 {
506        self.canonical_functions().resource_new(ty);
507        self.core_funcs.add(Some("resource.new"))
508    }
509
510    /// Declares a new `resource.rep` intrinsic.
511    pub fn resource_rep(&mut self, ty: u32) -> u32 {
512        self.canonical_functions().resource_rep(ty);
513        self.core_funcs.add(Some("resource.rep"))
514    }
515
516    /// Declares a new `thread.spawn_ref` intrinsic.
517    pub fn thread_spawn_ref(&mut self, ty: u32) -> u32 {
518        self.canonical_functions().thread_spawn_ref(ty);
519        self.core_funcs.add(Some("thread.spawn-ref"))
520    }
521
522    /// Declares a new `thread.available_parallelism` intrinsic.
523    pub fn thread_available_parallelism(&mut self) -> u32 {
524        self.canonical_functions().thread_available_parallelism();
525        self.core_funcs.add(Some("thread.available-parallelism"))
526    }
527
528    /// Declares a new `backpressure.inc` intrinsic.
529    pub fn backpressure_inc(&mut self) -> u32 {
530        self.canonical_functions().backpressure_inc();
531        self.core_funcs.add(Some("backpressure.inc"))
532    }
533
534    /// Declares a new `backpressure.dec` intrinsic.
535    pub fn backpressure_dec(&mut self) -> u32 {
536        self.canonical_functions().backpressure_dec();
537        self.core_funcs.add(Some("backpressure.dec"))
538    }
539
540    /// Declares a new `task.return` intrinsic.
541    pub fn task_return<O>(&mut self, ty: Option<ComponentValType>, options: O) -> u32
542    where
543        O: IntoIterator<Item = CanonicalOption>,
544        O::IntoIter: ExactSizeIterator,
545    {
546        self.canonical_functions().task_return(ty, options);
547        self.core_funcs.add(Some("task.return"))
548    }
549
550    /// Declares a new `task.cancel` intrinsic.
551    pub fn task_cancel(&mut self) -> u32 {
552        self.canonical_functions().task_cancel();
553        self.core_funcs.add(Some("task.cancel"))
554    }
555
556    /// Declares a new `context.get` intrinsic.
557    pub fn context_get(&mut self, ty: ValType, i: u32) -> u32 {
558        self.canonical_functions().context_get(ty, i);
559        self.core_funcs.add(Some(&format!("context.get {i}")))
560    }
561
562    /// Declares a new `context.set` intrinsic.
563    pub fn context_set(&mut self, ty: ValType, i: u32) -> u32 {
564        self.canonical_functions().context_set(ty, i);
565        self.core_funcs.add(Some(&format!("context.set {i}")))
566    }
567
568    /// Declares a new `subtask.drop` intrinsic.
569    pub fn subtask_drop(&mut self) -> u32 {
570        self.canonical_functions().subtask_drop();
571        self.core_funcs.add(Some("subtask.drop"))
572    }
573
574    /// Declares a new `subtask.cancel` intrinsic.
575    pub fn subtask_cancel(&mut self, async_: bool) -> u32 {
576        self.canonical_functions().subtask_cancel(async_);
577        self.core_funcs.add(Some("subtask.cancel"))
578    }
579
580    /// Declares a new `stream.new` intrinsic.
581    pub fn stream_new(&mut self, ty: u32) -> u32 {
582        self.canonical_functions().stream_new(ty);
583        self.core_funcs.add(Some("stream.new"))
584    }
585
586    /// Declares a new `stream.read` intrinsic.
587    pub fn stream_read<O>(&mut self, ty: u32, options: O) -> u32
588    where
589        O: IntoIterator<Item = CanonicalOption>,
590        O::IntoIter: ExactSizeIterator,
591    {
592        self.canonical_functions().stream_read(ty, options);
593        self.core_funcs.add(Some("stream.read"))
594    }
595
596    /// Declares a new `stream.write` intrinsic.
597    pub fn stream_write<O>(&mut self, ty: u32, options: O) -> u32
598    where
599        O: IntoIterator<Item = CanonicalOption>,
600        O::IntoIter: ExactSizeIterator,
601    {
602        self.canonical_functions().stream_write(ty, options);
603        self.core_funcs.add(Some("stream.write"))
604    }
605
606    /// Declares a new `stream.forward` intrinsic.
607    pub fn stream_forward(&mut self, ty: u32) -> u32 {
608        self.canonical_functions().stream_forward(ty);
609        self.core_funcs.add(Some("stream.forward"))
610    }
611
612    /// Declares a new `stream.cancel-read` intrinsic.
613    pub fn stream_cancel_read(&mut self, ty: u32, async_: bool) -> u32 {
614        self.canonical_functions().stream_cancel_read(ty, async_);
615        self.core_funcs.add(Some("stream.cancel-read"))
616    }
617
618    /// Declares a new `stream.cancel-write` intrinsic.
619    pub fn stream_cancel_write(&mut self, ty: u32, async_: bool) -> u32 {
620        self.canonical_functions().stream_cancel_write(ty, async_);
621        self.core_funcs.add(Some("stream.cancel-write"))
622    }
623
624    /// Declares a new `stream.drop-readable` intrinsic.
625    pub fn stream_drop_readable(&mut self, ty: u32) -> u32 {
626        self.canonical_functions().stream_drop_readable(ty);
627        self.core_funcs.add(Some("stream.drop-readable"))
628    }
629
630    /// Declares a new `stream.drop-writable` intrinsic.
631    pub fn stream_drop_writable(&mut self, ty: u32) -> u32 {
632        self.canonical_functions().stream_drop_writable(ty);
633        self.core_funcs.add(Some("stream.drop-writable"))
634    }
635
636    /// Declares a new `future.new` intrinsic.
637    pub fn future_new(&mut self, ty: u32) -> u32 {
638        self.canonical_functions().future_new(ty);
639        self.core_funcs.add(Some("future.new"))
640    }
641
642    /// Declares a new `future.read` intrinsic.
643    pub fn future_read<O>(&mut self, ty: u32, options: O) -> u32
644    where
645        O: IntoIterator<Item = CanonicalOption>,
646        O::IntoIter: ExactSizeIterator,
647    {
648        self.canonical_functions().future_read(ty, options);
649        self.core_funcs.add(Some("future.read"))
650    }
651
652    /// Declares a new `future.write` intrinsic.
653    pub fn future_write<O>(&mut self, ty: u32, options: O) -> u32
654    where
655        O: IntoIterator<Item = CanonicalOption>,
656        O::IntoIter: ExactSizeIterator,
657    {
658        self.canonical_functions().future_write(ty, options);
659        self.core_funcs.add(Some("future.write"))
660    }
661
662    /// Declares a new `future.forward` intrinsic.
663    pub fn future_forward(&mut self, ty: u32) -> u32 {
664        self.canonical_functions().future_forward(ty);
665        self.core_funcs.add(Some("future.forward"))
666    }
667
668    /// Declares a new `future.cancel-read` intrinsic.
669    pub fn future_cancel_read(&mut self, ty: u32, async_: bool) -> u32 {
670        self.canonical_functions().future_cancel_read(ty, async_);
671        self.core_funcs.add(Some("future.cancel-read"))
672    }
673
674    /// Declares a new `future.cancel-write` intrinsic.
675    pub fn future_cancel_write(&mut self, ty: u32, async_: bool) -> u32 {
676        self.canonical_functions().future_cancel_write(ty, async_);
677        self.core_funcs.add(Some("future.cancel-write"))
678    }
679
680    /// Declares a new `future.drop-readable` intrinsic.
681    pub fn future_drop_readable(&mut self, ty: u32) -> u32 {
682        self.canonical_functions().future_drop_readable(ty);
683        self.core_funcs.add(Some("future.drop-readable"))
684    }
685
686    /// Declares a new `future.drop-writable` intrinsic.
687    pub fn future_drop_writable(&mut self, ty: u32) -> u32 {
688        self.canonical_functions().future_drop_writable(ty);
689        self.core_funcs.add(Some("future.drop-writable"))
690    }
691
692    /// Declares a new `error-context.new` intrinsic.
693    pub fn error_context_new<O>(&mut self, options: O) -> u32
694    where
695        O: IntoIterator<Item = CanonicalOption>,
696        O::IntoIter: ExactSizeIterator,
697    {
698        self.canonical_functions().error_context_new(options);
699        self.core_funcs.add(Some("error-context.new"))
700    }
701
702    /// Declares a new `error-context.debug-message` intrinsic.
703    pub fn error_context_debug_message<O>(&mut self, options: O) -> u32
704    where
705        O: IntoIterator<Item = CanonicalOption>,
706        O::IntoIter: ExactSizeIterator,
707    {
708        self.canonical_functions()
709            .error_context_debug_message(options);
710        self.core_funcs.add(Some("error-context.debug-message"))
711    }
712
713    /// Declares a new `error-context.drop` intrinsic.
714    pub fn error_context_drop(&mut self) -> u32 {
715        self.canonical_functions().error_context_drop();
716        self.core_funcs.add(Some("error-context.drop"))
717    }
718
719    /// Declares a new `waitable-set.new` intrinsic.
720    pub fn waitable_set_new(&mut self) -> u32 {
721        self.canonical_functions().waitable_set_new();
722        self.core_funcs.add(Some("waitable-set.new"))
723    }
724
725    /// Declares a new `waitable-set.wait` intrinsic.
726    pub fn waitable_set_wait(&mut self, memory: u32) -> u32 {
727        self.canonical_functions().waitable_set_wait(memory);
728        self.core_funcs.add(Some("waitable-set.wait"))
729    }
730
731    /// Declares a new `waitable-set.poll` intrinsic.
732    pub fn waitable_set_poll(&mut self, memory: u32) -> u32 {
733        self.canonical_functions().waitable_set_poll(memory);
734        self.core_funcs.add(Some("waitable-set.poll"))
735    }
736
737    /// Declares a new `waitable-set.drop` intrinsic.
738    pub fn waitable_set_drop(&mut self) -> u32 {
739        self.canonical_functions().waitable_set_drop();
740        self.core_funcs.add(Some("waitable-set.drop"))
741    }
742
743    /// Declares a new `waitable.join` intrinsic.
744    pub fn waitable_join(&mut self) -> u32 {
745        self.canonical_functions().waitable_join();
746        self.core_funcs.add(Some("waitable.join"))
747    }
748
749    /// Declares a new `thread.index` intrinsic.
750    pub fn thread_index(&mut self) -> u32 {
751        self.canonical_functions().thread_index();
752        self.core_funcs.add(Some("thread.index"))
753    }
754
755    /// Declares a new `thread.new-indirect` intrinsic.
756    pub fn thread_new_indirect(&mut self, func_ty_idx: u32, table_index: u32) -> u32 {
757        self.canonical_functions()
758            .thread_new_indirect(func_ty_idx, table_index);
759        self.core_funcs.add(Some("thread.new-indirect"))
760    }
761
762    /// Declares a new `thread.resume-later` intrinsic.
763    pub fn thread_resume_later(&mut self) -> u32 {
764        self.canonical_functions().thread_resume_later();
765        self.core_funcs.add(Some("thread.resume-later"))
766    }
767
768    /// Declares a new `thread.suspend` intrinsic.
769    pub fn thread_suspend(&mut self) -> u32 {
770        self.canonical_functions().thread_suspend();
771        self.core_funcs.add(Some("thread.suspend"))
772    }
773
774    /// Declares a new `thread.yield` intrinsic.
775    pub fn thread_yield(&mut self) -> u32 {
776        self.canonical_functions().thread_yield();
777        self.core_funcs.add(Some("thread.yield"))
778    }
779
780    /// Declares a new `thread.suspend-then-resume` intrinsic.
781    pub fn thread_suspend_then_resume(&mut self) -> u32 {
782        self.canonical_functions().thread_suspend_then_resume();
783        self.core_funcs.add(Some("thread.suspend-then-resume"))
784    }
785
786    /// Declares a new `thread.yield-then-resume` intrinsic.
787    pub fn thread_yield_then_resume(&mut self) -> u32 {
788        self.canonical_functions().thread_yield_then_resume();
789        self.core_funcs.add(Some("thread.yield-then-resume"))
790    }
791
792    /// Declares a new `thread.suspend-then-promote` intrinsic.
793    pub fn thread_suspend_then_promote(&mut self) -> u32 {
794        self.canonical_functions().thread_suspend_then_promote();
795        self.core_funcs.add(Some("thread.suspend-then-promote"))
796    }
797
798    /// Declares a new `thread.yield-then-promote` intrinsic.
799    pub fn thread_yield_then_promote(&mut self) -> u32 {
800        self.canonical_functions().thread_yield_then_promote();
801        self.core_funcs.add(Some("thread.yield-then-resume"))
802    }
803
804    /// Adds a new custom section to this component.
805    pub fn custom_section(&mut self, section: &CustomSection<'_>) {
806        self.flush();
807        self.component.section(section);
808    }
809
810    /// Adds a new custom section to this component.
811    pub fn raw_custom_section(&mut self, section: &[u8]) {
812        self.flush();
813        self.component.section(&RawCustomSection(section));
814    }
815}
816
817// Helper macro to generate methods on `ComponentBuilder` to get specific
818// section encoders that automatically flush and write out prior sections as
819// necessary.
820macro_rules! section_accessors {
821    ($($method:ident => $section:ident)*) => (
822        #[derive(Debug, Default)]
823        enum LastSection {
824            #[default]
825            None,
826            $($section($section),)*
827        }
828
829        impl ComponentBuilder {
830            $(
831                fn $method(&mut self) -> &mut $section {
832                    match &self.last_section {
833                        // The last encoded section matches the section that's
834                        // being requested, so no change is necessary.
835                        LastSection::$section(_) => {}
836
837                        // Otherwise the last section didn't match this section,
838                        // so flush any prior section if needed and start
839                        // encoding the desired section of this method.
840                        _ => {
841                            self.flush();
842                            self.last_section = LastSection::$section($section::new());
843                        }
844                    }
845                    match &mut self.last_section {
846                        LastSection::$section(ret) => ret,
847                        _ => unreachable!()
848                    }
849                }
850            )*
851
852            /// Writes out the last section into the final component binary if
853            /// there is a section specified, otherwise does nothing.
854            fn flush(&mut self) {
855                match mem::take(&mut self.last_section) {
856                    LastSection::None => {}
857                    $(
858                        LastSection::$section(section) => {
859                            self.component.section(&section);
860                        }
861                    )*
862                }
863            }
864
865        }
866    )
867}
868
869section_accessors! {
870    component_instances => ComponentInstanceSection
871    instances => InstanceSection
872    canonical_functions => CanonicalFunctionSection
873    aliases => ComponentAliasSection
874    exports => ComponentExportSection
875    imports => ComponentImportSection
876    types => ComponentTypeSection
877    core_types => CoreTypeSection
878}
879
880#[derive(Debug, Default)]
881struct Namespace {
882    count: u32,
883    names: NameMap,
884}
885
886impl Namespace {
887    fn add(&mut self, name: Option<&str>) -> u32 {
888        let ret = self.count;
889        self.count += 1;
890        if let Some(name) = name {
891            self.names.append(ret, name);
892        }
893        ret
894    }
895}