summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wasm-encoder/src/component
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/wasm-encoder/src/component
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
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/canonicals.rs133
-rw-r--r--third_party/rust/wasm-encoder/src/component/components.rs29
-rw-r--r--third_party/rust/wasm-encoder/src/component/exports.rs125
-rw-r--r--third_party/rust/wasm-encoder/src/component/imports.rs151
-rw-r--r--third_party/rust/wasm-encoder/src/component/instances.rs199
-rw-r--r--third_party/rust/wasm-encoder/src/component/modules.rs29
-rw-r--r--third_party/rust/wasm-encoder/src/component/names.rs147
-rw-r--r--third_party/rust/wasm-encoder/src/component/start.rs52
-rw-r--r--third_party/rust/wasm-encoder/src/component/types.rs736
10 files changed, 1761 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/canonicals.rs b/third_party/rust/wasm-encoder/src/component/canonicals.rs
new file mode 100644
index 0000000000..e81819c44e
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/canonicals.rs
@@ -0,0 +1,133 @@
+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
+ }
+}
+
+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..9720d51b02
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/exports.rs
@@ -0,0 +1,125 @@
+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,
+ url: &str,
+ kind: ComponentExportKind,
+ index: u32,
+ ty: Option<ComponentTypeRef>,
+ ) -> &mut Self {
+ name.encode(&mut self.bytes);
+ url.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..8d843407f3
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/imports.rs
@@ -0,0 +1,151 @@
+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.
+ Eq,
+}
+
+impl Encode for TypeBounds {
+ fn encode(&self, sink: &mut Vec<u8>) {
+ match self {
+ Self::Eq => sink.push(0x00),
+ }
+ }
+}
+
+/// 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.
+ ///
+ /// The index is expected to be a type index.
+ Type(TypeBounds, u32),
+ /// 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, idx) => {
+ bounds.encode(sink);
+ idx.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, url: &str, ty: ComponentTypeRef) -> &mut Self {
+ name.encode(&mut self.bytes);
+ url.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()
+ }
+}
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..5f2c97dec3
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/instances.rs
@@ -0,0 +1,199 @@
+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 {
+ 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..0e3b02dc2e
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/names.rs
@@ -0,0 +1,147 @@
+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",
+ data: &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..930467d57a
--- /dev/null
+++ b/third_party/rust/wasm-encoder/src/component/types.rs
@@ -0,0 +1,736 @@
+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 {
+ self.bytes.push(0x00);
+ 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,
+}
+
+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,
+ _ => {}
+ }
+ self
+ }
+
+ /// Defines an import in this component type.
+ pub fn import(&mut self, name: &str, url: &str, ty: ComponentTypeRef) -> &mut Self {
+ self.bytes.push(0x03);
+ name.encode(&mut self.bytes);
+ url.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ match ty {
+ ComponentTypeRef::Type(..) => self.types_added += 1,
+ _ => {}
+ }
+ self
+ }
+
+ /// Defines an export in this component type.
+ pub fn export(&mut self, name: &str, url: &str, ty: ComponentTypeRef) -> &mut Self {
+ self.bytes.push(0x04);
+ name.encode(&mut self.bytes);
+ url.encode(&mut self.bytes);
+ ty.encode(&mut self.bytes);
+ self.num_added += 1;
+ match ty {
+ ComponentTypeRef::Type(..) => self.types_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
+ }
+}
+
+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, url: &str, ty: ComponentTypeRef) -> &mut Self {
+ self.0.export(name, url, 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
+ }
+
+ /// 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)
+ }
+}
+
+/// 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,
+ });
+ }
+}
+
+/// 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 a union type.
+ pub fn union<I, T>(self, types: I)
+ where
+ I: IntoIterator<Item = T>,
+ I::IntoIter: ExactSizeIterator,
+ T: Into<ComponentValType>,
+ {
+ let types = types.into_iter();
+ self.0.push(0x6C);
+ types.len().encode(self.0);
+ for ty in types {
+ ty.into().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);
+ }
+}
+
+/// 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()
+ }
+}
+
+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()
+ }
+}