summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wasm-encoder/src/component
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/wasm-encoder/src/component
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/wasm-encoder/src/component')
-rw-r--r--third_party/rust/wasm-encoder/src/component/aliases.rs160
-rw-r--r--third_party/rust/wasm-encoder/src/component/builder.rs455
-rw-r--r--third_party/rust/wasm-encoder/src/component/canonicals.rs159
-rw-r--r--third_party/rust/wasm-encoder/src/component/components.rs29
-rw-r--r--third_party/rust/wasm-encoder/src/component/exports.rs124
-rw-r--r--third_party/rust/wasm-encoder/src/component/imports.rs175
-rw-r--r--third_party/rust/wasm-encoder/src/component/instances.rs200
-rw-r--r--third_party/rust/wasm-encoder/src/component/modules.rs29
-rw-r--r--third_party/rust/wasm-encoder/src/component/names.rs149
-rw-r--r--third_party/rust/wasm-encoder/src/component/start.rs52
-rw-r--r--third_party/rust/wasm-encoder/src/component/types.rs792
11 files changed, 2324 insertions, 0 deletions
diff --git a/third_party/rust/wasm-encoder/src/component/aliases.rs b/third_party/rust/wasm-encoder/src/component/aliases.rs
new file mode 100644
index 0000000000..1e317fb0e2
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/aliases.rs
@@ -0,0 +1,160 @@
+use super::{COMPONENT_SORT, CORE_MODULE_SORT, CORE_SORT, CORE_TYPE_SORT, TYPE_SORT};
+use crate::{
+ encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, Encode, ExportKind,
+};
+
+/// Represents the kinds of outer aliasable items in a component.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ComponentOuterAliasKind {
+ /// The alias is to a core module.
+ CoreModule,
+ /// The alias is to a core type.
+ CoreType,
+ /// The alias is to a type.
+ Type,
+ /// The alias is to a component.
+ Component,
+}
+
+impl Encode for ComponentOuterAliasKind {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::CoreModule => {
+ sink.push(CORE_SORT);
+ sink.push(CORE_MODULE_SORT);
+ }
+ Self::CoreType => {
+ sink.push(CORE_SORT);
+ sink.push(CORE_TYPE_SORT);
+ }
+ Self::Type => sink.push(TYPE_SORT),
+ Self::Component => sink.push(COMPONENT_SORT),
+ }
+ }
+}
+
+/// An encoder for the alias section of WebAssembly component.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, Alias, ComponentAliasSection, ComponentExportKind, ComponentOuterAliasKind};
+///
+/// let mut aliases = ComponentAliasSection::new();
+/// aliases.alias(Alias::InstanceExport { instance: 0, kind: ComponentExportKind::Func, name: "f" });
+/// aliases.alias(Alias::Outer { count: 0, kind: ComponentOuterAliasKind::Type, index: 1 });
+///
+/// let mut component = Component::new();
+/// component.section(&aliases);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentAliasSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+/// Different forms of aliases that can be inserted into a
+/// [`ComponentAliasSection`].
+#[derive(Copy, Clone, Debug)]
+pub enum Alias<'a> {
+ /// An alias of a component instance export.
+ InstanceExport {
+ /// The index of the component instance that's being aliased from.
+ instance: u32,
+ /// The kind of item that's being extracted from the component
+ /// instance.
+ kind: ComponentExportKind,
+ /// The name of the export that's being aliased.
+ name: &'a str,
+ },
+ /// Same as `InstanceExport`, but for core instances.
+ #[allow(missing_docs)]
+ CoreInstanceExport {
+ instance: u32,
+ kind: ExportKind,
+ name: &'a str,
+ },
+ /// Aliasing an item from an outer component.
+ Outer {
+ /// The kind of item being aliased, either a type or a component.
+ kind: ComponentOuterAliasKind,
+ /// Number of levels "up" to go to lookup the index within. Level 0 is
+ /// the current scope and level 1 is the enclosing scope, and so on.
+ count: u32,
+ /// The index of the item to alias within the scope referenced by
+ /// `count`.
+ index: u32,
+ },
+}
+
+impl ComponentAliasSection {
+ /// Create a new alias section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of aliases in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an alias to a component instance's export.
+ pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self {
+ alias.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ComponentAliasSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentAliasSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Alias.into()
+ }
+}
+
+impl Encode for Alias<'_> {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Alias::InstanceExport {
+ instance,
+ kind,
+ name,
+ } => {
+ kind.encode(sink);
+ sink.push(0x00);
+ instance.encode(sink);
+ name.encode(sink);
+ }
+ Alias::CoreInstanceExport {
+ instance,
+ kind,
+ name,
+ } => {
+ sink.push(CORE_SORT);
+ kind.encode(sink);
+ sink.push(0x01);
+ instance.encode(sink);
+ name.encode(sink);
+ }
+ Alias::Outer { kind, count, index } => {
+ kind.encode(sink);
+ sink.push(0x02);
+ count.encode(sink);
+ index.encode(sink);
+ }
+ }
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/builder.rs b/third_party/rust/wasm-encoder/src/component/builder.rs
new file mode 100644
index 0000000000..27c39ac8a0
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/builder.rs
@@ -0,0 +1,455 @@
+use crate::component::*;
+use crate::{ExportKind, Module, RawSection, ValType};
+use std::mem;
+
+/// Convenience type to build a component incrementally and automatically keep
+/// track of index spaces.
+///
+/// This type is intended to be a wrapper around the [`Component`] encoding type
+/// which is useful for building it up incrementally over time. This type will
+/// automatically collect definitions into sections and reports the index of all
+/// items added by keeping track of indices internally.
+#[derive(Debug, Default)]
+pub struct ComponentBuilder {
+ /// The binary component that's being built.
+ component: Component,
+
+ /// The last section which was appended to during encoding. This type is
+ /// generated by the `section_accessors` macro below.
+ ///
+ /// When something is encoded this is used if it matches the kind of item
+ /// being encoded, otherwise it's "flushed" to the output component and a
+ /// new section is started.
+ last_section: LastSection,
+
+ // Core index spaces
+ core_modules: u32,
+ core_funcs: u32,
+ core_types: u32,
+ core_memories: u32,
+ core_tables: u32,
+ core_instances: u32,
+ core_tags: u32,
+ core_globals: u32,
+
+ // Component index spaces
+ funcs: u32,
+ instances: u32,
+ types: u32,
+ components: u32,
+ values: u32,
+}
+
+impl ComponentBuilder {
+ /// Returns the current number of core modules.
+ pub fn core_module_count(&self) -> u32 {
+ self.core_modules
+ }
+
+ /// Returns the current number of core funcs.
+ pub fn core_func_count(&self) -> u32 {
+ self.core_funcs
+ }
+
+ /// Returns the current number of core types.
+ pub fn core_type_count(&self) -> u32 {
+ self.core_types
+ }
+
+ /// Returns the current number of core memories.
+ pub fn core_memory_count(&self) -> u32 {
+ self.core_memories
+ }
+
+ /// Returns the current number of core tables.
+ pub fn core_table_count(&self) -> u32 {
+ self.core_tables
+ }
+
+ /// Returns the current number of core instances.
+ pub fn core_instance_count(&self) -> u32 {
+ self.core_instances
+ }
+
+ /// Returns the current number of core tags.
+ pub fn core_tag_count(&self) -> u32 {
+ self.core_tags
+ }
+
+ /// Returns the current number of core globals.
+ pub fn core_global_count(&self) -> u32 {
+ self.core_globals
+ }
+
+ /// Returns the current number of component funcs.
+ pub fn func_count(&self) -> u32 {
+ self.funcs
+ }
+
+ /// Returns the current number of component instances.
+ pub fn instance_count(&self) -> u32 {
+ self.instances
+ }
+
+ /// Returns the current number of component values.
+ pub fn value_count(&self) -> u32 {
+ self.values
+ }
+
+ /// Returns the current number of components.
+ pub fn component_count(&self) -> u32 {
+ self.components
+ }
+
+ /// Returns the current number of component types.
+ pub fn type_count(&self) -> u32 {
+ self.types
+ }
+
+ /// Completes this component and returns the binary encoding of the entire
+ /// component.
+ pub fn finish(mut self) -> Vec<u8> {
+ self.flush();
+ self.component.finish()
+ }
+
+ /// Encodes a core wasm `Module` into this component, returning its index.
+ pub fn core_module(&mut self, module: &Module) -> u32 {
+ self.flush();
+ self.component.section(&ModuleSection(module));
+ inc(&mut self.core_modules)
+ }
+
+ /// Encodes a core wasm `module` into this component, returning its index.
+ pub fn core_module_raw(&mut self, module: &[u8]) -> u32 {
+ self.flush();
+ self.component.section(&RawSection {
+ id: ComponentSectionId::CoreModule.into(),
+ data: module,
+ });
+ inc(&mut self.core_modules)
+ }
+
+ /// Instantiates a core wasm module at `module_index` with the `args`
+ /// provided.
+ ///
+ /// Returns the index of the core wasm instance crated.
+ pub fn core_instantiate<'a, A>(&mut self, module_index: u32, args: A) -> u32
+ where
+ A: IntoIterator<Item = (&'a str, ModuleArg)>,
+ A::IntoIter: ExactSizeIterator,
+ {
+ self.instances().instantiate(module_index, args);
+ inc(&mut self.core_instances)
+ }
+
+ /// Creates a new core wasm instance from the `exports` provided.
+ ///
+ /// Returns the index of the core wasm instance crated.
+ pub fn core_instantiate_exports<'a, E>(&mut self, exports: E) -> u32
+ where
+ E: IntoIterator<Item = (&'a str, ExportKind, u32)>,
+ E::IntoIter: ExactSizeIterator,
+ {
+ self.instances().export_items(exports);
+ inc(&mut self.core_instances)
+ }
+
+ /// Creates a new aliased item where the core `instance` specified has its
+ /// export `name` aliased out with the `kind` specified.
+ ///
+ /// Returns the index of the item crated.
+ pub fn core_alias_export(&mut self, instance: u32, name: &str, kind: ExportKind) -> u32 {
+ self.alias(Alias::CoreInstanceExport {
+ instance,
+ kind,
+ name,
+ })
+ }
+
+ /// Adds a new alias to this component
+ pub fn alias(&mut self, alias: Alias<'_>) -> u32 {
+ self.aliases().alias(alias);
+ match alias {
+ Alias::InstanceExport { kind, .. } => self.inc_kind(kind),
+ Alias::CoreInstanceExport { kind, .. } => self.inc_core_kind(kind),
+ Alias::Outer {
+ kind: ComponentOuterAliasKind::Type,
+ ..
+ } => inc(&mut self.types),
+ Alias::Outer {
+ kind: ComponentOuterAliasKind::CoreModule,
+ ..
+ } => inc(&mut self.core_modules),
+ Alias::Outer {
+ kind: ComponentOuterAliasKind::Component,
+ ..
+ } => inc(&mut self.components),
+ Alias::Outer {
+ kind: ComponentOuterAliasKind::CoreType,
+ ..
+ } => inc(&mut self.core_types),
+ }
+ }
+
+ /// Creates an alias to a previous component instance's exported item.
+ ///
+ /// The `instance` provided is the instance to access and the `name` is the
+ /// item to access.
+ ///
+ /// Returns the index of the new item defined.
+ pub fn alias_export(&mut self, instance: u32, name: &str, kind: ComponentExportKind) -> u32 {
+ self.alias(Alias::InstanceExport {
+ instance,
+ kind,
+ name,
+ })
+ }
+
+ fn inc_kind(&mut self, kind: ComponentExportKind) -> u32 {
+ match kind {
+ ComponentExportKind::Func => inc(&mut self.funcs),
+ ComponentExportKind::Module => inc(&mut self.core_modules),
+ ComponentExportKind::Type => inc(&mut self.types),
+ ComponentExportKind::Component => inc(&mut self.components),
+ ComponentExportKind::Instance => inc(&mut self.instances),
+ ComponentExportKind::Value => inc(&mut self.values),
+ }
+ }
+
+ fn inc_core_kind(&mut self, kind: ExportKind) -> u32 {
+ match kind {
+ ExportKind::Func => inc(&mut self.core_funcs),
+ ExportKind::Table => inc(&mut self.core_tables),
+ ExportKind::Memory => inc(&mut self.core_memories),
+ ExportKind::Global => inc(&mut self.core_globals),
+ ExportKind::Tag => inc(&mut self.core_tags),
+ }
+ }
+
+ /// Lowers the `func_index` component function into a core wasm function
+ /// using the `options` provided.
+ ///
+ /// Returns the index of the core wasm function created.
+ pub fn lower_func<O>(&mut self, func_index: u32, options: O) -> u32
+ where
+ O: IntoIterator<Item = CanonicalOption>,
+ O::IntoIter: ExactSizeIterator,
+ {
+ self.canonical_functions().lower(func_index, options);
+ inc(&mut self.core_funcs)
+ }
+
+ /// Lifts the core wasm `core_func_index` function with the component
+ /// function type `type_index` and `options`.
+ ///
+ /// Returns the index of the component function created.
+ pub fn lift_func<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> u32
+ where
+ O: IntoIterator<Item = CanonicalOption>,
+ O::IntoIter: ExactSizeIterator,
+ {
+ self.canonical_functions()
+ .lift(core_func_index, type_index, options);
+ inc(&mut self.funcs)
+ }
+
+ /// Imports a new item into this component with the `name` and `ty` specified.
+ pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> u32 {
+ let ret = match &ty {
+ ComponentTypeRef::Instance(_) => inc(&mut self.instances),
+ ComponentTypeRef::Func(_) => inc(&mut self.funcs),
+ ComponentTypeRef::Type(..) => inc(&mut self.types),
+ ComponentTypeRef::Component(_) => inc(&mut self.components),
+ ComponentTypeRef::Module(_) => inc(&mut self.core_modules),
+ ComponentTypeRef::Value(_) => inc(&mut self.values),
+ };
+ self.imports().import(name, ty);
+ ret
+ }
+
+ /// Exports a new item from this component with the `name` and `kind`
+ /// specified.
+ ///
+ /// The `idx` is the item to export and the `ty` is an optional type to
+ /// ascribe to the export.
+ pub fn export(
+ &mut self,
+ name: &str,
+ kind: ComponentExportKind,
+ idx: u32,
+ ty: Option<ComponentTypeRef>,
+ ) -> u32 {
+ self.exports().export(name, kind, idx, ty);
+ self.inc_kind(kind)
+ }
+
+ /// Creates a new encoder for the next core type in this component.
+ pub fn core_type(&mut self) -> (u32, CoreTypeEncoder<'_>) {
+ (inc(&mut self.core_types), self.core_types().ty())
+ }
+
+ /// Creates a new encoder for the next type in this component.
+ pub fn ty(&mut self) -> (u32, ComponentTypeEncoder<'_>) {
+ (inc(&mut self.types), self.types().ty())
+ }
+
+ /// Creates a new instance type within this component.
+ pub fn type_instance(&mut self, ty: &InstanceType) -> u32 {
+ self.types().instance(ty);
+ inc(&mut self.types)
+ }
+
+ /// Creates a new component type within this component.
+ pub fn type_component(&mut self, ty: &ComponentType) -> u32 {
+ self.types().component(ty);
+ inc(&mut self.types)
+ }
+
+ /// Creates a new defined component type within this component.
+ pub fn type_defined(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
+ (inc(&mut self.types), self.types().defined_type())
+ }
+
+ /// Creates a new component function type within this component.
+ pub fn type_function(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
+ (inc(&mut self.types), self.types().function())
+ }
+
+ /// Declares a
+ pub fn type_resource(&mut self, rep: ValType, dtor: Option<u32>) -> u32 {
+ self.types().resource(rep, dtor);
+ inc(&mut self.types)
+ }
+
+ /// Defines a new subcomponent of this component.
+ pub fn component(&mut self, mut builder: ComponentBuilder) -> u32 {
+ builder.flush();
+ self.flush();
+ self.component
+ .section(&NestedComponentSection(&builder.component));
+ inc(&mut self.components)
+ }
+
+ /// Defines a new subcomponent of this component.
+ pub fn component_raw(&mut self, data: &[u8]) -> u32 {
+ let raw_section = RawSection {
+ id: ComponentSectionId::Component.into(),
+ data,
+ };
+ self.flush();
+ self.component.section(&raw_section);
+ inc(&mut self.components)
+ }
+
+ /// Instantiates the `component_index` specified with the `args` specified.
+ pub fn instantiate<A, S>(&mut self, component_index: u32, args: A) -> u32
+ where
+ A: IntoIterator<Item = (S, ComponentExportKind, u32)>,
+ A::IntoIter: ExactSizeIterator,
+ S: AsRef<str>,
+ {
+ self.component_instances()
+ .instantiate(component_index, args);
+ inc(&mut self.instances)
+ }
+
+ /// Declares a new `resource.drop` intrinsic.
+ pub fn resource_drop(&mut self, ty: u32) -> u32 {
+ self.canonical_functions().resource_drop(ty);
+ inc(&mut self.core_funcs)
+ }
+
+ /// Declares a new `resource.new` intrinsic.
+ pub fn resource_new(&mut self, ty: u32) -> u32 {
+ self.canonical_functions().resource_new(ty);
+ inc(&mut self.core_funcs)
+ }
+
+ /// Declares a new `resource.rep` intrinsic.
+ pub fn resource_rep(&mut self, ty: u32) -> u32 {
+ self.canonical_functions().resource_rep(ty);
+ inc(&mut self.core_funcs)
+ }
+
+ /// Adds a new custom section to this component.
+ pub fn custom_section(&mut self, section: &CustomSection<'_>) {
+ self.flush();
+ self.component.section(section);
+ }
+
+ /// Adds a new custom section to this component.
+ pub fn raw_custom_section(&mut self, section: &[u8]) {
+ self.flush();
+ self.component.section(&RawCustomSection(section));
+ }
+}
+
+// Helper macro to generate methods on `ComponentBuilder` to get specific
+// section encoders that automatically flush and write out prior sections as
+// necessary.
+macro_rules! section_accessors {
+ ($($method:ident => $section:ident)*) => (
+ #[derive(Debug, Default)]
+ enum LastSection {
+ #[default]
+ None,
+ $($section($section),)*
+ }
+
+ impl ComponentBuilder {
+ $(
+ fn $method(&mut self) -> &mut $section {
+ match &self.last_section {
+ // The last encoded section matches the section that's
+ // being requested, so no change is necessary.
+ LastSection::$section(_) => {}
+
+ // Otherwise the last section didn't match this section,
+ // so flush any prior section if needed and start
+ // encoding the desired section of this method.
+ _ => {
+ self.flush();
+ self.last_section = LastSection::$section($section::new());
+ }
+ }
+ match &mut self.last_section {
+ LastSection::$section(ret) => ret,
+ _ => unreachable!()
+ }
+ }
+ )*
+
+ /// Writes out the last section into the final component binary if
+ /// there is a section specified, otherwise does nothing.
+ fn flush(&mut self) {
+ match mem::take(&mut self.last_section) {
+ LastSection::None => {}
+ $(
+ LastSection::$section(section) => {
+ self.component.section(&section);
+ }
+ )*
+ }
+ }
+
+ }
+ )
+}
+
+section_accessors! {
+ component_instances => ComponentInstanceSection
+ instances => InstanceSection
+ canonical_functions => CanonicalFunctionSection
+ aliases => ComponentAliasSection
+ exports => ComponentExportSection
+ imports => ComponentImportSection
+ types => ComponentTypeSection
+ core_types => CoreTypeSection
+}
+
+fn inc(idx: &mut u32) -> u32 {
+ let ret = *idx;
+ *idx += 1;
+ ret
+}
diff --git a/third_party/rust/wasm-encoder/src/component/canonicals.rs b/third_party/rust/wasm-encoder/src/component/canonicals.rs
new file mode 100644
index 0000000000..340d9ca621
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/canonicals.rs
@@ -0,0 +1,159 @@
+use crate::{encode_section, ComponentSection, ComponentSectionId, Encode};
+
+/// Represents options for canonical function definitions.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum CanonicalOption {
+ /// The string types in the function signature are UTF-8 encoded.
+ UTF8,
+ /// The string types in the function signature are UTF-16 encoded.
+ UTF16,
+ /// The string types in the function signature are compact UTF-16 encoded.
+ CompactUTF16,
+ /// The memory to use if the lifting or lowering of a function requires memory access.
+ ///
+ /// The value is an index to a core memory.
+ Memory(u32),
+ /// The realloc function to use if the lifting or lowering of a function requires memory
+ /// allocation.
+ ///
+ /// The value is an index to a core function of type `(func (param i32 i32 i32 i32) (result i32))`.
+ Realloc(u32),
+ /// The post-return function to use if the lifting of a function requires
+ /// cleanup after the function returns.
+ PostReturn(u32),
+}
+
+impl Encode for CanonicalOption {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::UTF8 => sink.push(0x00),
+ Self::UTF16 => sink.push(0x01),
+ Self::CompactUTF16 => sink.push(0x02),
+ Self::Memory(idx) => {
+ sink.push(0x03);
+ idx.encode(sink);
+ }
+ Self::Realloc(idx) => {
+ sink.push(0x04);
+ idx.encode(sink);
+ }
+ Self::PostReturn(idx) => {
+ sink.push(0x05);
+ idx.encode(sink);
+ }
+ }
+ }
+}
+
+/// An encoder for the canonical function section of WebAssembly components.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{Component, CanonicalFunctionSection, CanonicalOption};
+///
+/// let mut functions = CanonicalFunctionSection::new();
+/// functions.lift(0, 0, [CanonicalOption::UTF8]);
+///
+/// let mut component = Component::new();
+/// component.section(&functions);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct CanonicalFunctionSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl CanonicalFunctionSection {
+ /// Construct a new component function section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of functions in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define a function that will lift a core WebAssembly function to the canonical ABI.
+ pub fn lift<O>(&mut self, core_func_index: u32, type_index: u32, options: O) -> &mut Self
+ where
+ O: IntoIterator<Item = CanonicalOption>,
+ O::IntoIter: ExactSizeIterator,
+ {
+ let options = options.into_iter();
+ self.bytes.push(0x00);
+ self.bytes.push(0x00);
+ core_func_index.encode(&mut self.bytes);
+ options.len().encode(&mut self.bytes);
+ for option in options {
+ option.encode(&mut self.bytes);
+ }
+ type_index.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Define a function that will lower a canonical ABI function to a core WebAssembly function.
+ pub fn lower<O>(&mut self, func_index: u32, options: O) -> &mut Self
+ where
+ O: IntoIterator<Item = CanonicalOption>,
+ O::IntoIter: ExactSizeIterator,
+ {
+ let options = options.into_iter();
+ self.bytes.push(0x01);
+ self.bytes.push(0x00);
+ func_index.encode(&mut self.bytes);
+ options.len().encode(&mut self.bytes);
+ for option in options {
+ option.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+
+ /// Defines a function which will create an owned handle to the resource
+ /// specified by `ty_index`.
+ pub fn resource_new(&mut self, ty_index: u32) -> &mut Self {
+ self.bytes.push(0x02);
+ ty_index.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Defines a function which will drop the specified type of handle.
+ pub fn resource_drop(&mut self, ty_index: u32) -> &mut Self {
+ self.bytes.push(0x03);
+ ty_index.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Defines a function which will return the representation of the specified
+ /// resource type.
+ pub fn resource_rep(&mut self, ty_index: u32) -> &mut Self {
+ self.bytes.push(0x04);
+ ty_index.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for CanonicalFunctionSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for CanonicalFunctionSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CanonicalFunction.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/components.rs b/third_party/rust/wasm-encoder/src/component/components.rs
new file mode 100644
index 0000000000..c08645e3b9
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/components.rs
@@ -0,0 +1,29 @@
+use crate::{Component, ComponentSection, ComponentSectionId, Encode};
+
+/// An encoder for the component section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, NestedComponentSection};
+///
+/// let mut nested = Component::new();
+/// let mut component = Component::new();
+/// component.section(&NestedComponentSection(&nested));
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug)]
+pub struct NestedComponentSection<'a>(pub &'a Component);
+
+impl Encode for NestedComponentSection<'_> {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.0.bytes.encode(sink);
+ }
+}
+
+impl ComponentSection for NestedComponentSection<'_> {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Component.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/exports.rs b/third_party/rust/wasm-encoder/src/component/exports.rs
new file mode 100644
index 0000000000..e4fcfee055
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/exports.rs
@@ -0,0 +1,124 @@
+use super::{
+ COMPONENT_SORT, CORE_MODULE_SORT, CORE_SORT, FUNCTION_SORT, INSTANCE_SORT, TYPE_SORT,
+ VALUE_SORT,
+};
+use crate::{encode_section, ComponentSection, ComponentSectionId, ComponentTypeRef, Encode};
+
+/// Represents the kind of an export from a WebAssembly component.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ComponentExportKind {
+ /// The export is a core module.
+ Module,
+ /// The export is a function.
+ Func,
+ /// The export is a value.
+ Value,
+ /// The export is a type.
+ Type,
+ /// The export is an instance.
+ Instance,
+ /// The export is a component.
+ Component,
+}
+
+impl Encode for ComponentExportKind {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::Module => {
+ sink.push(CORE_SORT);
+ sink.push(CORE_MODULE_SORT);
+ }
+ Self::Func => {
+ sink.push(FUNCTION_SORT);
+ }
+ Self::Value => {
+ sink.push(VALUE_SORT);
+ }
+ Self::Type => {
+ sink.push(TYPE_SORT);
+ }
+ Self::Instance => {
+ sink.push(INSTANCE_SORT);
+ }
+ Self::Component => {
+ sink.push(COMPONENT_SORT);
+ }
+ }
+ }
+}
+
+/// An encoder for the export section of WebAssembly component.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, ComponentExportSection, ComponentExportKind};
+///
+/// // This exports a function named "foo"
+/// let mut exports = ComponentExportSection::new();
+/// exports.export("foo", ComponentExportKind::Func, 0, None);
+///
+/// let mut component = Component::new();
+/// component.section(&exports);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentExportSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ComponentExportSection {
+ /// Create a new component export section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of exports in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an export in the export section.
+ pub fn export(
+ &mut self,
+ name: &str,
+ kind: ComponentExportKind,
+ index: u32,
+ ty: Option<ComponentTypeRef>,
+ ) -> &mut Self {
+ crate::component::imports::push_extern_name_byte(&mut self.bytes, name);
+ name.encode(&mut self.bytes);
+ kind.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ match ty {
+ Some(ty) => {
+ self.bytes.push(0x01);
+ ty.encode(&mut self.bytes);
+ }
+ None => {
+ self.bytes.push(0x00);
+ }
+ }
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ComponentExportSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentExportSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Export.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/imports.rs b/third_party/rust/wasm-encoder/src/component/imports.rs
new file mode 100644
index 0000000000..6337a0625d
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/imports.rs
@@ -0,0 +1,175 @@
+use crate::{
+ encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, ComponentValType,
+ Encode,
+};
+
+/// Represents the possible type bounds for type references.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub enum TypeBounds {
+ /// The type is bounded by equality to the type index specified.
+ Eq(u32),
+ /// This type is a fresh resource type,
+ SubResource,
+}
+
+impl Encode for TypeBounds {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::Eq(i) => {
+ sink.push(0x00);
+ i.encode(sink);
+ }
+ Self::SubResource => sink.push(0x01),
+ }
+ }
+}
+
+/// Represents a reference to a type.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
+pub enum ComponentTypeRef {
+ /// The reference is to a core module type.
+ ///
+ /// The index is expected to be core type index to a core module type.
+ Module(u32),
+ /// The reference is to a function type.
+ ///
+ /// The index is expected to be a type index to a function type.
+ Func(u32),
+ /// The reference is to a value type.
+ Value(ComponentValType),
+ /// The reference is to a bounded type.
+ Type(TypeBounds),
+ /// The reference is to an instance type.
+ ///
+ /// The index is expected to be a type index to an instance type.
+ Instance(u32),
+ /// The reference is to a component type.
+ ///
+ /// The index is expected to be a type index to a component type.
+ Component(u32),
+}
+
+impl ComponentTypeRef {
+ /// Gets the export kind of the reference.
+ pub fn kind(&self) -> ComponentExportKind {
+ match self {
+ Self::Module(_) => ComponentExportKind::Module,
+ Self::Func(_) => ComponentExportKind::Func,
+ Self::Value(_) => ComponentExportKind::Value,
+ Self::Type(..) => ComponentExportKind::Type,
+ Self::Instance(_) => ComponentExportKind::Instance,
+ Self::Component(_) => ComponentExportKind::Component,
+ }
+ }
+}
+
+impl Encode for ComponentTypeRef {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.kind().encode(sink);
+
+ match self {
+ Self::Module(idx) | Self::Func(idx) | Self::Instance(idx) | Self::Component(idx) => {
+ idx.encode(sink);
+ }
+ Self::Value(ty) => ty.encode(sink),
+ Self::Type(bounds) => bounds.encode(sink),
+ }
+ }
+}
+
+/// An encoder for the import section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType, ComponentImportSection, ComponentTypeRef};
+///
+/// let mut types = ComponentTypeSection::new();
+///
+/// // Define a function type of `[string, string] -> string`.
+/// types
+/// .function()
+/// .params(
+/// [
+/// ("a", PrimitiveValType::String),
+/// ("b", PrimitiveValType::String)
+/// ]
+/// )
+/// .result(PrimitiveValType::String);
+///
+/// // This imports a function named `f` with the type defined above
+/// let mut imports = ComponentImportSection::new();
+/// imports.import("f", ComponentTypeRef::Func(0));
+///
+/// let mut component = Component::new();
+/// component.section(&types);
+/// component.section(&imports);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentImportSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ComponentImportSection {
+ /// Create a new component import section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of imports in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an import in the component import section.
+ pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self {
+ push_extern_name_byte(&mut self.bytes, name);
+ name.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ComponentImportSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentImportSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Import.into()
+ }
+}
+
+/// Prior to WebAssembly/component-model#263 import and export names were
+/// discriminated with a leading byte indicating what kind of import they are.
+/// After that PR though names are always prefixed with a 0x00 byte.
+///
+/// This function is a compatibility shim for the time being while this change
+/// is being rolled out. That PR is technically a spec-breaking change relative
+/// to prior but we want old tooling to continue to work with new modules. To
+/// handle that names that look like IDs, `a:b/c`, get an 0x01 prefix instead of
+/// the spec-defined 0x00 prefix. That makes components produced by current
+/// versions of this crate compatible with older parsers.
+///
+/// Note that wasmparser has a similar case where it parses either 0x01 or 0x00.
+/// That means that the selection of a byte here doesn't actually matter for
+/// wasmparser's own validation. Eventually this will go away and an 0x00 byte
+/// will always be emitted to align with the spec.
+pub(crate) fn push_extern_name_byte(bytes: &mut Vec<u8>, name: &str) {
+ if name.contains(':') {
+ bytes.push(0x01);
+ } else {
+ bytes.push(0x00);
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/instances.rs b/third_party/rust/wasm-encoder/src/component/instances.rs
new file mode 100644
index 0000000000..e0877d1661
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/instances.rs
@@ -0,0 +1,200 @@
+use super::CORE_INSTANCE_SORT;
+use crate::{
+ encode_section, ComponentExportKind, ComponentSection, ComponentSectionId, Encode, ExportKind,
+};
+
+/// Represents an argument to a module instantiation.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ModuleArg {
+ /// The argument is an instance.
+ Instance(u32),
+}
+
+impl Encode for ModuleArg {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ let (sort, idx) = match self {
+ Self::Instance(idx) => (CORE_INSTANCE_SORT, *idx),
+ };
+ sink.push(sort);
+ idx.encode(sink);
+ }
+}
+
+/// An encoder for the core instance section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, InstanceSection, ExportKind, ModuleArg};
+///
+/// let mut instances = InstanceSection::new();
+/// instances.export_items([("foo", ExportKind::Func, 0)]);
+/// instances.instantiate(1, [("foo", ModuleArg::Instance(0))]);
+///
+/// let mut component = Component::new();
+/// component.section(&instances);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct InstanceSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl InstanceSection {
+ /// Create a new core instance section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of instances in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an instance by instantiating a core module.
+ pub fn instantiate<A, S>(&mut self, module_index: u32, args: A) -> &mut Self
+ where
+ A: IntoIterator<Item = (S, ModuleArg)>,
+ A::IntoIter: ExactSizeIterator,
+ S: AsRef<str>,
+ {
+ let args = args.into_iter();
+ self.bytes.push(0x00);
+ module_index.encode(&mut self.bytes);
+ args.len().encode(&mut self.bytes);
+ for (name, arg) in args {
+ name.as_ref().encode(&mut self.bytes);
+ arg.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+
+ /// Define an instance by exporting core WebAssembly items.
+ pub fn export_items<E, S>(&mut self, exports: E) -> &mut Self
+ where
+ E: IntoIterator<Item = (S, ExportKind, u32)>,
+ E::IntoIter: ExactSizeIterator,
+ S: AsRef<str>,
+ {
+ let exports = exports.into_iter();
+ self.bytes.push(0x01);
+ exports.len().encode(&mut self.bytes);
+ for (name, kind, index) in exports {
+ name.as_ref().encode(&mut self.bytes);
+ kind.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for InstanceSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for InstanceSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CoreInstance.into()
+ }
+}
+
+/// An encoder for the instance section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, ComponentInstanceSection, ComponentExportKind};
+///
+/// let mut instances = ComponentInstanceSection::new();
+/// instances.export_items([("foo", ComponentExportKind::Func, 0)]);
+/// instances.instantiate(1, [("foo", ComponentExportKind::Instance, 0)]);
+///
+/// let mut component = Component::new();
+/// component.section(&instances);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentInstanceSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ComponentInstanceSection {
+ /// Create a new instance section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of instances in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Define an instance by instantiating a component.
+ pub fn instantiate<A, S>(&mut self, component_index: u32, args: A) -> &mut Self
+ where
+ A: IntoIterator<Item = (S, ComponentExportKind, u32)>,
+ A::IntoIter: ExactSizeIterator,
+ S: AsRef<str>,
+ {
+ let args = args.into_iter();
+ self.bytes.push(0x00);
+ component_index.encode(&mut self.bytes);
+ args.len().encode(&mut self.bytes);
+ for (name, kind, index) in args {
+ name.as_ref().encode(&mut self.bytes);
+ kind.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+
+ /// Define an instance by exporting items.
+ pub fn export_items<'a, E>(&mut self, exports: E) -> &mut Self
+ where
+ E: IntoIterator<Item = (&'a str, ComponentExportKind, u32)>,
+ E::IntoIter: ExactSizeIterator,
+ {
+ let exports = exports.into_iter();
+ self.bytes.push(0x01);
+ exports.len().encode(&mut self.bytes);
+ for (name, kind, index) in exports {
+ crate::push_extern_name_byte(&mut self.bytes, name);
+ name.encode(&mut self.bytes);
+ kind.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ }
+ self.num_added += 1;
+ self
+ }
+}
+
+impl Encode for ComponentInstanceSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentInstanceSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Instance.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/modules.rs b/third_party/rust/wasm-encoder/src/component/modules.rs
new file mode 100644
index 0000000000..437cd353af
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/modules.rs
@@ -0,0 +1,29 @@
+use crate::{ComponentSection, ComponentSectionId, Encode, Module};
+
+/// An encoder for the module section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Module, Component, ModuleSection};
+///
+/// let mut module = Module::new();
+/// let mut component = Component::new();
+/// component.section(&ModuleSection(&module));
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug)]
+pub struct ModuleSection<'a>(pub &'a Module);
+
+impl Encode for ModuleSection<'_> {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.0.bytes.encode(sink);
+ }
+}
+
+impl ComponentSection for ModuleSection<'_> {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CoreModule.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/names.rs b/third_party/rust/wasm-encoder/src/component/names.rs
new file mode 100644
index 0000000000..99db10bda0
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/names.rs
@@ -0,0 +1,149 @@
+use std::borrow::Cow;
+
+use super::*;
+use crate::{encoding_size, CustomSection, Encode, ExportKind, NameMap, SectionId};
+
+/// Encoding for the `component-name` custom section which assigns
+/// human-readable names to items within a component.
+#[derive(Clone, Debug, Default)]
+pub struct ComponentNameSection {
+ bytes: Vec<u8>,
+}
+
+enum Subsection {
+ Component,
+ Decls,
+}
+
+impl ComponentNameSection {
+ /// Creates a new blank `name` custom section.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Appends a component name subsection to this section.
+ ///
+ /// This will indicate that the name of the entire component should be the
+ /// `name` specified. Note that this should be encoded first before other
+ /// subsections.
+ pub fn component(&mut self, name: &str) {
+ let len = encoding_size(u32::try_from(name.len()).unwrap());
+ self.subsection_header(Subsection::Component, len + name.len());
+ name.encode(&mut self.bytes);
+ }
+
+ /// Appends a decls name subsection to name core functions within the
+ /// component.
+ pub fn core_funcs(&mut self, names: &NameMap) {
+ self.core_decls(ExportKind::Func as u8, names)
+ }
+
+ /// Appends a decls name subsection to name core tables within the
+ /// component.
+ pub fn core_tables(&mut self, names: &NameMap) {
+ self.core_decls(ExportKind::Table as u8, names)
+ }
+
+ /// Appends a decls name subsection to name core memories within the
+ /// component.
+ pub fn core_memories(&mut self, names: &NameMap) {
+ self.core_decls(ExportKind::Memory as u8, names)
+ }
+
+ /// Appends a decls name subsection to name core globals within the
+ /// component.
+ pub fn core_globals(&mut self, names: &NameMap) {
+ self.core_decls(ExportKind::Global as u8, names)
+ }
+
+ /// Appends a decls name subsection to name core types within the
+ /// component.
+ pub fn core_types(&mut self, names: &NameMap) {
+ self.core_decls(CORE_TYPE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name core modules within the
+ /// component.
+ pub fn core_modules(&mut self, names: &NameMap) {
+ self.core_decls(CORE_MODULE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name core instances within the
+ /// component.
+ pub fn core_instances(&mut self, names: &NameMap) {
+ self.core_decls(CORE_INSTANCE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name component functions within the
+ /// component.
+ pub fn funcs(&mut self, names: &NameMap) {
+ self.component_decls(FUNCTION_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name component values within the
+ /// component.
+ pub fn values(&mut self, names: &NameMap) {
+ self.component_decls(VALUE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name component type within the
+ /// component.
+ pub fn types(&mut self, names: &NameMap) {
+ self.component_decls(TYPE_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name components within the
+ /// component.
+ pub fn components(&mut self, names: &NameMap) {
+ self.component_decls(COMPONENT_SORT, names)
+ }
+
+ /// Appends a decls name subsection to name component instances within the
+ /// component.
+ pub fn instances(&mut self, names: &NameMap) {
+ self.component_decls(INSTANCE_SORT, names)
+ }
+
+ fn component_decls(&mut self, kind: u8, names: &NameMap) {
+ self.subsection_header(Subsection::Decls, 1 + names.size());
+ self.bytes.push(kind);
+ names.encode(&mut self.bytes);
+ }
+
+ fn core_decls(&mut self, kind: u8, names: &NameMap) {
+ self.subsection_header(Subsection::Decls, 2 + names.size());
+ self.bytes.push(CORE_SORT);
+ self.bytes.push(kind);
+ names.encode(&mut self.bytes);
+ }
+
+ fn subsection_header(&mut self, id: Subsection, len: usize) {
+ self.bytes.push(id as u8);
+ len.encode(&mut self.bytes);
+ }
+
+ /// Returns whether this section is empty, or nothing has been encoded.
+ pub fn is_empty(&self) -> bool {
+ self.bytes.is_empty()
+ }
+
+ /// View the encoded section as a CustomSection.
+ pub fn as_custom<'a>(&'a self) -> CustomSection<'a> {
+ CustomSection {
+ name: "component-name".into(),
+ data: Cow::Borrowed(&self.bytes),
+ }
+ }
+}
+
+impl Encode for ComponentNameSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ self.as_custom().encode(sink);
+ }
+}
+
+impl ComponentSection for ComponentNameSection {
+ fn id(&self) -> u8 {
+ SectionId::Custom.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/start.rs b/third_party/rust/wasm-encoder/src/component/start.rs
new file mode 100644
index 0000000000..d4b60e1dfc
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/start.rs
@@ -0,0 +1,52 @@
+use crate::{ComponentSection, ComponentSectionId, Encode};
+
+/// An encoder for the start section of WebAssembly components.
+///
+/// # Example
+///
+/// ```
+/// use wasm_encoder::{Component, ComponentStartSection};
+///
+/// let start = ComponentStartSection { function_index: 0, args: [0, 1], results: 1 };
+///
+/// let mut component = Component::new();
+/// component.section(&start);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug)]
+pub struct ComponentStartSection<A> {
+ /// The index to the start function.
+ pub function_index: u32,
+ /// The arguments to pass to the start function.
+ ///
+ /// An argument is an index to a value.
+ pub args: A,
+ /// The number of expected results for the start function.
+ ///
+ /// This should match the number of results for the type of
+ /// the function referenced by `function_index`.
+ pub results: u32,
+}
+
+impl<A> Encode for ComponentStartSection<A>
+where
+ A: AsRef<[u32]>,
+{
+ fn encode(&self, sink: &mut Vec<u8>) {
+ let mut bytes = Vec::new();
+ self.function_index.encode(&mut bytes);
+ self.args.as_ref().encode(&mut bytes);
+ self.results.encode(&mut bytes);
+ bytes.encode(sink);
+ }
+}
+
+impl<A> ComponentSection for ComponentStartSection<A>
+where
+ A: AsRef<[u32]>,
+{
+ fn id(&self) -> u8 {
+ ComponentSectionId::Start.into()
+ }
+}
diff --git a/third_party/rust/wasm-encoder/src/component/types.rs b/third_party/rust/wasm-encoder/src/component/types.rs
new file mode 100644
index 0000000000..537e8c5a00
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/types.rs
@@ -0,0 +1,792 @@
+use super::CORE_TYPE_SORT;
+use crate::{
+ encode_section, Alias, ComponentExportKind, ComponentOuterAliasKind, ComponentSection,
+ ComponentSectionId, ComponentTypeRef, Encode, EntityType, ValType,
+};
+
+/// Represents the type of a core module.
+#[derive(Debug, Clone, Default)]
+pub struct ModuleType {
+ bytes: Vec<u8>,
+ num_added: u32,
+ types_added: u32,
+}
+
+impl ModuleType {
+ /// Creates a new core module type.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Defines an import in this module type.
+ pub fn import(&mut self, module: &str, name: &str, ty: EntityType) -> &mut Self {
+ crate::component::imports::push_extern_name_byte(&mut self.bytes, name);
+ module.encode(&mut self.bytes);
+ name.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Define a type in this module type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> CoreTypeEncoder {
+ self.bytes.push(0x01);
+ self.num_added += 1;
+ self.types_added += 1;
+ CoreTypeEncoder(&mut self.bytes)
+ }
+
+ /// Defines an outer core type alias in this module type.
+ pub fn alias_outer_core_type(&mut self, count: u32, index: u32) -> &mut Self {
+ self.bytes.push(0x02);
+ self.bytes.push(CORE_TYPE_SORT);
+ self.bytes.push(0x01); // outer
+ count.encode(&mut self.bytes);
+ index.encode(&mut self.bytes);
+ self.num_added += 1;
+ self.types_added += 1;
+ self
+ }
+
+ /// Defines an export in this module type.
+ pub fn export(&mut self, name: &str, ty: EntityType) -> &mut Self {
+ self.bytes.push(0x03);
+ name.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ self
+ }
+
+ /// Gets the number of types that have been added to this module type.
+ pub fn type_count(&self) -> u32 {
+ self.types_added
+ }
+}
+
+impl Encode for ModuleType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(0x50);
+ self.num_added.encode(sink);
+ sink.extend(&self.bytes);
+ }
+}
+
+/// Used to encode core types.
+#[derive(Debug)]
+pub struct CoreTypeEncoder<'a>(pub(crate) &'a mut Vec<u8>);
+
+impl<'a> CoreTypeEncoder<'a> {
+ /// Define a function type.
+ pub fn function<P, R>(self, params: P, results: R)
+ where
+ P: IntoIterator<Item = ValType>,
+ P::IntoIter: ExactSizeIterator,
+ R: IntoIterator<Item = ValType>,
+ R::IntoIter: ExactSizeIterator,
+ {
+ let params = params.into_iter();
+ let results = results.into_iter();
+
+ self.0.push(0x60);
+ params.len().encode(self.0);
+ params.for_each(|p| p.encode(self.0));
+ results.len().encode(self.0);
+ results.for_each(|p| p.encode(self.0));
+ }
+
+ /// Define a module type.
+ pub fn module(self, ty: &ModuleType) {
+ ty.encode(self.0);
+ }
+}
+
+/// An encoder for the core type section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, CoreTypeSection, ModuleType};
+///
+/// let mut types = CoreTypeSection::new();
+///
+/// types.module(&ModuleType::new());
+///
+/// let mut component = Component::new();
+/// component.section(&types);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct CoreTypeSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl CoreTypeSection {
+ /// Create a new core type section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of types in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Encode a type into this section.
+ ///
+ /// The returned encoder must be finished before adding another type.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> CoreTypeEncoder<'_> {
+ self.num_added += 1;
+ CoreTypeEncoder(&mut self.bytes)
+ }
+
+ /// Define a function type in this type section.
+ pub fn function<P, R>(&mut self, params: P, results: R) -> &mut Self
+ where
+ P: IntoIterator<Item = ValType>,
+ P::IntoIter: ExactSizeIterator,
+ R: IntoIterator<Item = ValType>,
+ R::IntoIter: ExactSizeIterator,
+ {
+ self.ty().function(params, results);
+ self
+ }
+
+ /// Define a module type in this type section.
+ ///
+ /// Currently this is only used for core type sections in components.
+ pub fn module(&mut self, ty: &ModuleType) -> &mut Self {
+ self.ty().module(ty);
+ self
+ }
+}
+
+impl Encode for CoreTypeSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for CoreTypeSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::CoreType.into()
+ }
+}
+
+/// Represents a component type.
+#[derive(Debug, Clone, Default)]
+pub struct ComponentType {
+ bytes: Vec<u8>,
+ num_added: u32,
+ core_types_added: u32,
+ types_added: u32,
+ instances_added: u32,
+}
+
+impl ComponentType {
+ /// Creates a new component type.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Define a core type in this component type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn core_type(&mut self) -> CoreTypeEncoder {
+ self.bytes.push(0x00);
+ self.num_added += 1;
+ self.core_types_added += 1;
+ CoreTypeEncoder(&mut self.bytes)
+ }
+
+ /// Define a type in this component type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> ComponentTypeEncoder {
+ self.bytes.push(0x01);
+ self.num_added += 1;
+ self.types_added += 1;
+ ComponentTypeEncoder(&mut self.bytes)
+ }
+
+ /// Defines an alias for an exported item of a prior instance or an
+ /// outer type.
+ pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self {
+ self.bytes.push(0x02);
+ alias.encode(&mut self.bytes);
+ self.num_added += 1;
+ match &alias {
+ Alias::InstanceExport {
+ kind: ComponentExportKind::Type,
+ ..
+ }
+ | Alias::Outer {
+ kind: ComponentOuterAliasKind::Type,
+ ..
+ } => self.types_added += 1,
+ Alias::Outer {
+ kind: ComponentOuterAliasKind::CoreType,
+ ..
+ } => self.core_types_added += 1,
+ Alias::InstanceExport {
+ kind: ComponentExportKind::Instance,
+ ..
+ } => self.instances_added += 1,
+ _ => {}
+ }
+ self
+ }
+
+ /// Defines an import in this component type.
+ pub fn import(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self {
+ self.bytes.push(0x03);
+ crate::component::imports::push_extern_name_byte(&mut self.bytes, name);
+ name.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ match ty {
+ ComponentTypeRef::Type(..) => self.types_added += 1,
+ ComponentTypeRef::Instance(..) => self.instances_added += 1,
+ _ => {}
+ }
+ self
+ }
+
+ /// Defines an export in this component type.
+ pub fn export(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self {
+ self.bytes.push(0x04);
+ crate::component::imports::push_extern_name_byte(&mut self.bytes, name);
+ name.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ match ty {
+ ComponentTypeRef::Type(..) => self.types_added += 1,
+ ComponentTypeRef::Instance(..) => self.instances_added += 1,
+ _ => {}
+ }
+ self
+ }
+
+ /// Gets the number of core types that have been added to this component type.
+ pub fn core_type_count(&self) -> u32 {
+ self.core_types_added
+ }
+
+ /// Gets the number of types that have been added or aliased in this component type.
+ pub fn type_count(&self) -> u32 {
+ self.types_added
+ }
+
+ /// Gets the number of instances that have been defined in this component
+ /// type through imports, exports, or aliases.
+ pub fn instance_count(&self) -> u32 {
+ self.instances_added
+ }
+}
+
+impl Encode for ComponentType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(0x41);
+ self.num_added.encode(sink);
+ sink.extend(&self.bytes);
+ }
+}
+
+/// Represents an instance type.
+#[derive(Debug, Clone, Default)]
+pub struct InstanceType(ComponentType);
+
+impl InstanceType {
+ /// Creates a new instance type.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Define a core type in this instance type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn core_type(&mut self) -> CoreTypeEncoder {
+ self.0.core_type()
+ }
+
+ /// Define a type in this instance type.
+ ///
+ /// The returned encoder must be used before adding another definition.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> ComponentTypeEncoder {
+ self.0.ty()
+ }
+
+ /// Defines an outer core type alias in this component type.
+ pub fn alias(&mut self, alias: Alias<'_>) -> &mut Self {
+ self.0.alias(alias);
+ self
+ }
+
+ /// Defines an export in this instance type.
+ pub fn export(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self {
+ self.0.export(name, ty);
+ self
+ }
+
+ /// Gets the number of core types that have been added to this instance type.
+ pub fn core_type_count(&self) -> u32 {
+ self.0.core_types_added
+ }
+
+ /// Gets the number of types that have been added or aliased in this instance type.
+ pub fn type_count(&self) -> u32 {
+ self.0.types_added
+ }
+
+ /// Gets the number of instances that have been imported or exported or
+ /// aliased in this instance type.
+ pub fn instance_count(&self) -> u32 {
+ self.0.instances_added
+ }
+
+ /// Returns whether or not this instance type is empty.
+ pub fn is_empty(&self) -> bool {
+ self.0.num_added == 0
+ }
+
+ /// Returns the number of entries added to this instance types.
+ pub fn len(&self) -> u32 {
+ self.0.num_added
+ }
+}
+
+impl Encode for InstanceType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(0x42);
+ self.0.num_added.encode(sink);
+ sink.extend(&self.0.bytes);
+ }
+}
+
+/// Used to encode component function types.
+#[derive(Debug)]
+pub struct ComponentFuncTypeEncoder<'a>(&'a mut Vec<u8>);
+
+impl<'a> ComponentFuncTypeEncoder<'a> {
+ fn new(sink: &'a mut Vec<u8>) -> Self {
+ sink.push(0x40);
+ Self(sink)
+ }
+
+ /// Defines named parameters.
+ ///
+ /// Parameters must be defined before defining results.
+ pub fn params<'b, P, T>(&mut self, params: P) -> &mut Self
+ where
+ P: IntoIterator<Item = (&'b str, T)>,
+ P::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ let params = params.into_iter();
+ params.len().encode(self.0);
+ for (name, ty) in params {
+ name.encode(self.0);
+ ty.into().encode(self.0);
+ }
+ self
+ }
+
+ /// Defines a single unnamed result.
+ ///
+ /// This method cannot be used with `results`.
+ pub fn result(&mut self, ty: impl Into<ComponentValType>) -> &mut Self {
+ self.0.push(0x00);
+ ty.into().encode(self.0);
+ self
+ }
+
+ /// Defines named results.
+ ///
+ /// This method cannot be used with `result`.
+ pub fn results<'b, R, T>(&mut self, results: R) -> &mut Self
+ where
+ R: IntoIterator<Item = (&'b str, T)>,
+ R::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ self.0.push(0x01);
+ let results = results.into_iter();
+ results.len().encode(self.0);
+ for (name, ty) in results {
+ name.encode(self.0);
+ ty.into().encode(self.0);
+ }
+ self
+ }
+}
+
+/// Used to encode component and instance types.
+#[derive(Debug)]
+pub struct ComponentTypeEncoder<'a>(&'a mut Vec<u8>);
+
+impl<'a> ComponentTypeEncoder<'a> {
+ /// Define a component type.
+ pub fn component(self, ty: &ComponentType) {
+ ty.encode(self.0);
+ }
+
+ /// Define an instance type.
+ pub fn instance(self, ty: &InstanceType) {
+ ty.encode(self.0);
+ }
+
+ /// Define a function type.
+ pub fn function(self) -> ComponentFuncTypeEncoder<'a> {
+ ComponentFuncTypeEncoder::new(self.0)
+ }
+
+ /// Define a defined component type.
+ ///
+ /// The returned encoder must be used before adding another type.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn defined_type(self) -> ComponentDefinedTypeEncoder<'a> {
+ ComponentDefinedTypeEncoder(self.0)
+ }
+
+ /// Define a resource type.
+ pub fn resource(self, rep: ValType, dtor: Option<u32>) {
+ self.0.push(0x3f);
+ rep.encode(self.0);
+ match dtor {
+ Some(i) => {
+ self.0.push(0x01);
+ i.encode(self.0);
+ }
+ None => self.0.push(0x00),
+ }
+ }
+}
+
+/// Represents a primitive component value type.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum PrimitiveValType {
+ /// The type is a boolean.
+ Bool,
+ /// The type is a signed 8-bit integer.
+ S8,
+ /// The type is an unsigned 8-bit integer.
+ U8,
+ /// The type is a signed 16-bit integer.
+ S16,
+ /// The type is an unsigned 16-bit integer.
+ U16,
+ /// The type is a signed 32-bit integer.
+ S32,
+ /// The type is an unsigned 32-bit integer.
+ U32,
+ /// The type is a signed 64-bit integer.
+ S64,
+ /// The type is an unsigned 64-bit integer.
+ U64,
+ /// The type is a 32-bit floating point number.
+ Float32,
+ /// The type is a 64-bit floating point number.
+ Float64,
+ /// The type is a Unicode character.
+ Char,
+ /// The type is a string.
+ String,
+}
+
+impl Encode for PrimitiveValType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ sink.push(match self {
+ Self::Bool => 0x7f,
+ Self::S8 => 0x7e,
+ Self::U8 => 0x7d,
+ Self::S16 => 0x7c,
+ Self::U16 => 0x7b,
+ Self::S32 => 0x7a,
+ Self::U32 => 0x79,
+ Self::S64 => 0x78,
+ Self::U64 => 0x77,
+ Self::Float32 => 0x76,
+ Self::Float64 => 0x75,
+ Self::Char => 0x74,
+ Self::String => 0x73,
+ });
+ }
+}
+
+#[cfg(feature = "wasmparser")]
+impl From<wasmparser::PrimitiveValType> for PrimitiveValType {
+ fn from(ty: wasmparser::PrimitiveValType) -> Self {
+ match ty {
+ wasmparser::PrimitiveValType::Bool => PrimitiveValType::Bool,
+ wasmparser::PrimitiveValType::S8 => PrimitiveValType::S8,
+ wasmparser::PrimitiveValType::U8 => PrimitiveValType::U8,
+ wasmparser::PrimitiveValType::S16 => PrimitiveValType::S16,
+ wasmparser::PrimitiveValType::U16 => PrimitiveValType::U16,
+ wasmparser::PrimitiveValType::S32 => PrimitiveValType::S32,
+ wasmparser::PrimitiveValType::U32 => PrimitiveValType::U32,
+ wasmparser::PrimitiveValType::S64 => PrimitiveValType::S64,
+ wasmparser::PrimitiveValType::U64 => PrimitiveValType::U64,
+ wasmparser::PrimitiveValType::Float32 => PrimitiveValType::Float32,
+ wasmparser::PrimitiveValType::Float64 => PrimitiveValType::Float64,
+ wasmparser::PrimitiveValType::Char => PrimitiveValType::Char,
+ wasmparser::PrimitiveValType::String => PrimitiveValType::String,
+ }
+ }
+}
+
+/// Represents a component value type.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ComponentValType {
+ /// The value is a primitive type.
+ Primitive(PrimitiveValType),
+ /// The value is to a defined value type.
+ ///
+ /// The type index must be to a value type.
+ Type(u32),
+}
+
+impl Encode for ComponentValType {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::Primitive(ty) => ty.encode(sink),
+ Self::Type(index) => (*index as i64).encode(sink),
+ }
+ }
+}
+
+impl From<PrimitiveValType> for ComponentValType {
+ fn from(ty: PrimitiveValType) -> Self {
+ Self::Primitive(ty)
+ }
+}
+
+/// Used for encoding component defined types.
+#[derive(Debug)]
+pub struct ComponentDefinedTypeEncoder<'a>(&'a mut Vec<u8>);
+
+impl ComponentDefinedTypeEncoder<'_> {
+ /// Define a primitive value type.
+ pub fn primitive(self, ty: PrimitiveValType) {
+ ty.encode(self.0);
+ }
+
+ /// Define a record type.
+ pub fn record<'a, F, T>(self, fields: F)
+ where
+ F: IntoIterator<Item = (&'a str, T)>,
+ F::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ let fields = fields.into_iter();
+ self.0.push(0x72);
+ fields.len().encode(self.0);
+ for (name, ty) in fields {
+ name.encode(self.0);
+ ty.into().encode(self.0);
+ }
+ }
+
+ /// Define a variant type.
+ pub fn variant<'a, C>(self, cases: C)
+ where
+ C: IntoIterator<Item = (&'a str, Option<ComponentValType>, Option<u32>)>,
+ C::IntoIter: ExactSizeIterator,
+ {
+ let cases = cases.into_iter();
+ self.0.push(0x71);
+ cases.len().encode(self.0);
+ for (name, ty, refines) in cases {
+ name.encode(self.0);
+ ty.encode(self.0);
+ refines.encode(self.0);
+ }
+ }
+
+ /// Define a list type.
+ pub fn list(self, ty: impl Into<ComponentValType>) {
+ self.0.push(0x70);
+ ty.into().encode(self.0);
+ }
+
+ /// Define a tuple type.
+ pub fn tuple<I, T>(self, types: I)
+ where
+ I: IntoIterator<Item = T>,
+ I::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ let types = types.into_iter();
+ self.0.push(0x6F);
+ types.len().encode(self.0);
+ for ty in types {
+ ty.into().encode(self.0);
+ }
+ }
+
+ /// Define a flags type.
+ pub fn flags<'a, I>(self, names: I)
+ where
+ I: IntoIterator<Item = &'a str>,
+ I::IntoIter: ExactSizeIterator,
+ {
+ let names = names.into_iter();
+ self.0.push(0x6E);
+ names.len().encode(self.0);
+ for name in names {
+ name.encode(self.0);
+ }
+ }
+
+ /// Define an enum type.
+ pub fn enum_type<'a, I>(self, tags: I)
+ where
+ I: IntoIterator<Item = &'a str>,
+ I::IntoIter: ExactSizeIterator,
+ {
+ let tags = tags.into_iter();
+ self.0.push(0x6D);
+ tags.len().encode(self.0);
+ for tag in tags {
+ tag.encode(self.0);
+ }
+ }
+
+ /// Define an option type.
+ pub fn option(self, ty: impl Into<ComponentValType>) {
+ self.0.push(0x6B);
+ ty.into().encode(self.0);
+ }
+
+ /// Define a result type.
+ pub fn result(self, ok: Option<ComponentValType>, err: Option<ComponentValType>) {
+ self.0.push(0x6A);
+ ok.encode(self.0);
+ err.encode(self.0);
+ }
+
+ /// Define a `own` handle type
+ pub fn own(self, idx: u32) {
+ self.0.push(0x69);
+ idx.encode(self.0);
+ }
+
+ /// Define a `borrow` handle type
+ pub fn borrow(self, idx: u32) {
+ self.0.push(0x68);
+ idx.encode(self.0);
+ }
+}
+
+/// An encoder for the type section of WebAssembly components.
+///
+/// # Example
+///
+/// ```rust
+/// use wasm_encoder::{Component, ComponentTypeSection, PrimitiveValType};
+///
+/// let mut types = ComponentTypeSection::new();
+///
+/// // Define a function type of `[string, string] -> string`.
+/// types
+/// .function()
+/// .params(
+/// [
+/// ("a", PrimitiveValType::String),
+/// ("b", PrimitiveValType::String)
+/// ]
+/// )
+/// .result(PrimitiveValType::String);
+///
+/// let mut component = Component::new();
+/// component.section(&types);
+///
+/// let bytes = component.finish();
+/// ```
+#[derive(Clone, Debug, Default)]
+pub struct ComponentTypeSection {
+ bytes: Vec<u8>,
+ num_added: u32,
+}
+
+impl ComponentTypeSection {
+ /// Create a new component type section encoder.
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// The number of types in the section.
+ pub fn len(&self) -> u32 {
+ self.num_added
+ }
+
+ /// Determines if the section is empty.
+ pub fn is_empty(&self) -> bool {
+ self.num_added == 0
+ }
+
+ /// Encode a type into this section.
+ ///
+ /// The returned encoder must be finished before adding another type.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn ty(&mut self) -> ComponentTypeEncoder<'_> {
+ self.num_added += 1;
+ ComponentTypeEncoder(&mut self.bytes)
+ }
+
+ /// Define a component type in this type section.
+ pub fn component(&mut self, ty: &ComponentType) -> &mut Self {
+ self.ty().component(ty);
+ self
+ }
+
+ /// Define an instance type in this type section.
+ pub fn instance(&mut self, ty: &InstanceType) -> &mut Self {
+ self.ty().instance(ty);
+ self
+ }
+
+ /// Define a function type in this type section.
+ pub fn function(&mut self) -> ComponentFuncTypeEncoder<'_> {
+ self.ty().function()
+ }
+
+ /// Add a component defined type to this type section.
+ ///
+ /// The returned encoder must be used before adding another type.
+ #[must_use = "the encoder must be used to encode the type"]
+ pub fn defined_type(&mut self) -> ComponentDefinedTypeEncoder<'_> {
+ self.ty().defined_type()
+ }
+
+ /// Defines a new resource type.
+ pub fn resource(&mut self, rep: ValType, dtor: Option<u32>) -> &mut Self {
+ self.ty().resource(rep, dtor);
+ self
+ }
+}
+
+impl Encode for ComponentTypeSection {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ encode_section(sink, self.num_added, &self.bytes);
+ }
+}
+
+impl ComponentSection for ComponentTypeSection {
+ fn id(&self) -> u8 {
+ ComponentSectionId::Type.into()
+ }
+}