diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/wasm-encoder/src/component | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/wasm-encoder/src/component')
9 files changed, 1574 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..a78d52643a --- /dev/null +++ b/third_party/rust/wasm-encoder/src/component/aliases.rs @@ -0,0 +1,129 @@ +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, ComponentAliasSection, ComponentExportKind, ComponentOuterAliasKind}; +/// +/// let mut aliases = ComponentAliasSection::new(); +/// aliases.instance_export(0, ComponentExportKind::Func, "f"); +/// aliases.outer(0, ComponentOuterAliasKind::Type, 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, +} + +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 instance_export( + &mut self, + instance_index: u32, + kind: ComponentExportKind, + name: &str, + ) -> &mut Self { + kind.encode(&mut self.bytes); + self.bytes.push(0x00); + instance_index.encode(&mut self.bytes); + name.encode(&mut self.bytes); + self.num_added += 1; + self + } + + /// Define an alias to a core instance's export. + pub fn core_instance_export( + &mut self, + instance_index: u32, + kind: ExportKind, + name: &str, + ) -> &mut Self { + self.bytes.push(CORE_SORT); + kind.encode(&mut self.bytes); + self.bytes.push(0x01); + instance_index.encode(&mut self.bytes); + name.encode(&mut self.bytes); + self.num_added += 1; + self + } + + /// Define an alias to an outer component item. + /// + /// The count starts at 0 to indicate the current component, 1 indicates the direct + /// parent, 2 the grandparent, etc. + pub fn outer(&mut self, count: u32, kind: ComponentOuterAliasKind, index: u32) -> &mut Self { + kind.encode(&mut self.bytes); + self.bytes.push(0x02); + count.encode(&mut self.bytes); + index.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() + } +} 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..eefd3ca0ec --- /dev/null +++ b/third_party/rust/wasm-encoder/src/component/exports.rs @@ -0,0 +1,108 @@ +use super::{ + COMPONENT_SORT, CORE_MODULE_SORT, CORE_SORT, FUNCTION_SORT, INSTANCE_SORT, TYPE_SORT, + VALUE_SORT, +}; +use crate::{encode_section, ComponentSection, ComponentSectionId, 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); +/// +/// 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) -> &mut Self { + name.encode(&mut self.bytes); + kind.encode(&mut self.bytes); + index.encode(&mut self.bytes); + 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..641163f3f5 --- /dev/null +++ b/third_party/rust/wasm-encoder/src/component/imports.rs @@ -0,0 +1,150 @@ +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, ty: ComponentTypeRef) -> &mut Self { + 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() + } +} 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..000a872d6b --- /dev/null +++ b/third_party/rust/wasm-encoder/src/component/instances.rs @@ -0,0 +1,196 @@ +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, A>(&mut self, module_index: u32, args: A) -> &mut Self + where + A: IntoIterator<Item = (&'a str, ModuleArg)>, + A::IntoIter: ExactSizeIterator, + { + 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.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<'a, E>(&mut self, exports: E) -> &mut Self + where + E: IntoIterator<Item = (&'a str, ExportKind, 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 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, A>(&mut self, component_index: u32, args: A) -> &mut Self + where + A: IntoIterator<Item = (&'a str, ComponentExportKind, u32)>, + A::IntoIter: ExactSizeIterator, + { + 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.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/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..8b097c9834 --- /dev/null +++ b/third_party/rust/wasm-encoder/src/component/types.rs @@ -0,0 +1,748 @@ +use super::CORE_TYPE_SORT; +use crate::{ + encode_section, 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); + self.0.extend(params.map(u8::from)); + results.len().encode(self.0); + self.0.extend(results.map(u8::from)); + } + + /// 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 outer core type alias in this component type. + pub fn alias_outer_core_type(&mut self, count: u32, index: u32) -> &mut Self { + self.bytes.push(0x02); + ComponentOuterAliasKind::CoreType.encode(&mut self.bytes); + self.bytes.push(0x02); + count.encode(&mut self.bytes); + index.encode(&mut self.bytes); + self.num_added += 1; + self.core_types_added += 1; + self + } + + /// Defines an outer type alias in this component type. + pub fn alias_outer_type(&mut self, count: u32, index: u32) -> &mut Self { + self.bytes.push(0x02); + ComponentOuterAliasKind::Type.encode(&mut self.bytes); + self.bytes.push(0x02); + count.encode(&mut self.bytes); + index.encode(&mut self.bytes); + self.num_added += 1; + self.types_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); + name.encode(&mut self.bytes); + ty.encode(&mut self.bytes); + self.num_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); + name.encode(&mut self.bytes); + ty.encode(&mut self.bytes); + self.num_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 { + bytes: Vec<u8>, + num_added: u32, + core_types_added: u32, + types_added: u32, +} + +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.bytes.push(0x00); + self.num_added += 1; + self.core_types_added += 1; + CoreTypeEncoder(&mut self.bytes) + } + + /// 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.bytes.push(0x01); + self.num_added += 1; + self.types_added += 1; + ComponentTypeEncoder(&mut self.bytes) + } + + /// Defines an outer core type alias in this component type. + pub fn alias_outer_core_type(&mut self, count: u32, index: u32) -> &mut Self { + self.bytes.push(0x02); + ComponentOuterAliasKind::CoreType.encode(&mut self.bytes); + self.bytes.push(0x02); + count.encode(&mut self.bytes); + index.encode(&mut self.bytes); + self.num_added += 1; + self.core_types_added += 1; + self + } + + /// Defines an alias in this instance type. + pub fn alias_outer_type(&mut self, count: u32, index: u32) -> &mut Self { + self.bytes.push(0x02); + ComponentOuterAliasKind::Type.encode(&mut self.bytes); + self.bytes.push(0x02); + count.encode(&mut self.bytes); + index.encode(&mut self.bytes); + self.num_added += 1; + self.types_added += 1; + self + } + + /// Defines an export in this instance type. + pub fn export(&mut self, name: &str, ty: ComponentTypeRef) -> &mut Self { + self.bytes.push(0x04); + name.encode(&mut self.bytes); + ty.encode(&mut self.bytes); + self.num_added += 1; + self + } + + /// Gets the number of core types that have been added to this instance 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 instance type. + pub fn type_count(&self) -> u32 { + self.types_added + } +} + +impl Encode for InstanceType { + fn encode(&self, sink: &mut Vec<u8>) { + sink.push(0x42); + self.num_added.encode(sink); + sink.extend(&self.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() + } +} |