summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wasmparser/src/readers/component
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wasmparser/src/readers/component')
-rw-r--r--third_party/rust/wasmparser/src/readers/component/aliases.rs119
-rw-r--r--third_party/rust/wasmparser/src/readers/component/canonicals.rs95
-rw-r--r--third_party/rust/wasmparser/src/readers/component/exports.rs105
-rw-r--r--third_party/rust/wasmparser/src/readers/component/imports.rs109
-rw-r--r--third_party/rust/wasmparser/src/readers/component/instances.rs164
-rw-r--r--third_party/rust/wasmparser/src/readers/component/names.rs102
-rw-r--r--third_party/rust/wasmparser/src/readers/component/start.rs30
-rw-r--r--third_party/rust/wasmparser/src/readers/component/types.rs508
8 files changed, 1232 insertions, 0 deletions
diff --git a/third_party/rust/wasmparser/src/readers/component/aliases.rs b/third_party/rust/wasmparser/src/readers/component/aliases.rs
new file mode 100644
index 0000000000..fb71d579b4
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/aliases.rs
@@ -0,0 +1,119 @@
+use crate::{BinaryReader, ComponentExternalKind, ExternalKind, FromReader, Result};
+
+/// Represents the kind of an outer alias in a WebAssembly 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 component type.
+ Type,
+ /// The alias is to a component.
+ Component,
+}
+
+/// Represents an alias in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub enum ComponentAlias<'a> {
+ /// The alias is to an export of a component instance.
+ InstanceExport {
+ /// The alias kind.
+ kind: ComponentExternalKind,
+ /// The instance index.
+ instance_index: u32,
+ /// The export name.
+ name: &'a str,
+ },
+ /// The alias is to an export of a module instance.
+ CoreInstanceExport {
+ /// The alias kind.
+ kind: ExternalKind,
+ /// The instance index.
+ instance_index: u32,
+ /// The export name.
+ name: &'a str,
+ },
+ /// The alias is to an outer item.
+ Outer {
+ /// The alias kind.
+ kind: ComponentOuterAliasKind,
+ /// The outward count, starting at zero for the current component.
+ count: u32,
+ /// The index of the item within the outer component.
+ index: u32,
+ },
+}
+
+/// Section reader for the component alias section
+pub type ComponentAliasSectionReader<'a> = crate::SectionLimited<'a, ComponentAlias<'a>>;
+
+impl<'a> FromReader<'a> for ComponentAlias<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ // We don't know what type of alias it is yet, so just read the sort bytes
+ let offset = reader.original_position();
+ let byte1 = reader.read_u8()?;
+ let byte2 = if byte1 == 0x00 {
+ Some(reader.read_u8()?)
+ } else {
+ None
+ };
+
+ Ok(match reader.read_u8()? {
+ 0x00 => ComponentAlias::InstanceExport {
+ kind: ComponentExternalKind::from_bytes(byte1, byte2, offset)?,
+ instance_index: reader.read_var_u32()?,
+ name: reader.read_string()?,
+ },
+ 0x01 => ComponentAlias::CoreInstanceExport {
+ kind: BinaryReader::external_kind_from_byte(
+ byte2.ok_or_else(|| {
+ BinaryReader::invalid_leading_byte_error(
+ byte1,
+ "core instance export kind",
+ offset,
+ )
+ })?,
+ offset,
+ )?,
+ instance_index: reader.read_var_u32()?,
+ name: reader.read_string()?,
+ },
+ 0x02 => ComponentAlias::Outer {
+ kind: component_outer_alias_kind_from_bytes(byte1, byte2, offset)?,
+ count: reader.read_var_u32()?,
+ index: reader.read_var_u32()?,
+ },
+ x => reader.invalid_leading_byte(x, "alias")?,
+ })
+ }
+}
+
+fn component_outer_alias_kind_from_bytes(
+ byte1: u8,
+ byte2: Option<u8>,
+ offset: usize,
+) -> Result<ComponentOuterAliasKind> {
+ Ok(match byte1 {
+ 0x00 => match byte2.unwrap() {
+ 0x10 => ComponentOuterAliasKind::CoreType,
+ 0x11 => ComponentOuterAliasKind::CoreModule,
+ x => {
+ return Err(BinaryReader::invalid_leading_byte_error(
+ x,
+ "component outer alias kind",
+ offset + 1,
+ ))
+ }
+ },
+ 0x03 => ComponentOuterAliasKind::Type,
+ 0x04 => ComponentOuterAliasKind::Component,
+ x => {
+ return Err(BinaryReader::invalid_leading_byte_error(
+ x,
+ "component outer alias kind",
+ offset,
+ ))
+ }
+ })
+}
diff --git a/third_party/rust/wasmparser/src/readers/component/canonicals.rs b/third_party/rust/wasmparser/src/readers/component/canonicals.rs
new file mode 100644
index 0000000000..e360d029c4
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/canonicals.rs
@@ -0,0 +1,95 @@
+use crate::limits::MAX_WASM_CANONICAL_OPTIONS;
+use crate::{BinaryReader, FromReader, Result, SectionLimited};
+
+/// Represents options for component functions.
+#[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),
+}
+
+/// Represents a canonical function in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub enum CanonicalFunction {
+ /// The function lifts a core WebAssembly function to the canonical ABI.
+ Lift {
+ /// The index of the core WebAssembly function to lift.
+ core_func_index: u32,
+ /// The index of the lifted function's type.
+ type_index: u32,
+ /// The canonical options for the function.
+ options: Box<[CanonicalOption]>,
+ },
+ /// The function lowers a canonical ABI function to a core WebAssembly function.
+ Lower {
+ /// The index of the function to lower.
+ func_index: u32,
+ /// The canonical options for the function.
+ options: Box<[CanonicalOption]>,
+ },
+}
+
+/// A reader for the canonical section of a WebAssembly component.
+pub type ComponentCanonicalSectionReader<'a> = SectionLimited<'a, CanonicalFunction>;
+
+impl<'a> FromReader<'a> for CanonicalFunction {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<CanonicalFunction> {
+ Ok(match reader.read_u8()? {
+ 0x00 => match reader.read_u8()? {
+ 0x00 => {
+ let core_func_index = reader.read_var_u32()?;
+ let options = reader
+ .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options")?
+ .collect::<Result<_>>()?;
+ let type_index = reader.read_var_u32()?;
+ CanonicalFunction::Lift {
+ core_func_index,
+ options,
+ type_index,
+ }
+ }
+ x => return reader.invalid_leading_byte(x, "canonical function lift"),
+ },
+ 0x01 => match reader.read_u8()? {
+ 0x00 => CanonicalFunction::Lower {
+ func_index: reader.read_var_u32()?,
+ options: reader
+ .read_iter(MAX_WASM_CANONICAL_OPTIONS, "canonical options")?
+ .collect::<Result<_>>()?,
+ },
+ x => return reader.invalid_leading_byte(x, "canonical function lower"),
+ },
+ x => return reader.invalid_leading_byte(x, "canonical function"),
+ })
+ }
+}
+
+impl<'a> FromReader<'a> for CanonicalOption {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x00 => CanonicalOption::UTF8,
+ 0x01 => CanonicalOption::UTF16,
+ 0x02 => CanonicalOption::CompactUTF16,
+ 0x03 => CanonicalOption::Memory(reader.read_var_u32()?),
+ 0x04 => CanonicalOption::Realloc(reader.read_var_u32()?),
+ 0x05 => CanonicalOption::PostReturn(reader.read_var_u32()?),
+ x => return reader.invalid_leading_byte(x, "canonical option"),
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/component/exports.rs b/third_party/rust/wasmparser/src/readers/component/exports.rs
new file mode 100644
index 0000000000..8ce5f43a00
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/exports.rs
@@ -0,0 +1,105 @@
+use crate::{BinaryReader, ComponentTypeRef, FromReader, Result, SectionLimited};
+
+/// Represents the kind of an external items of a WebAssembly component.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ComponentExternalKind {
+ /// The external kind is a core module.
+ Module,
+ /// The external kind is a function.
+ Func,
+ /// The external kind is a value.
+ Value,
+ /// The external kind is a type.
+ Type,
+ /// The external kind is an instance.
+ Instance,
+ /// The external kind is a component.
+ Component,
+}
+
+impl ComponentExternalKind {
+ pub(crate) fn from_bytes(
+ byte1: u8,
+ byte2: Option<u8>,
+ offset: usize,
+ ) -> Result<ComponentExternalKind> {
+ Ok(match byte1 {
+ 0x00 => match byte2.unwrap() {
+ 0x11 => ComponentExternalKind::Module,
+ x => {
+ return Err(BinaryReader::invalid_leading_byte_error(
+ x,
+ "component external kind",
+ offset + 1,
+ ))
+ }
+ },
+ 0x01 => ComponentExternalKind::Func,
+ 0x02 => ComponentExternalKind::Value,
+ 0x03 => ComponentExternalKind::Type,
+ 0x04 => ComponentExternalKind::Component,
+ 0x05 => ComponentExternalKind::Instance,
+ x => {
+ return Err(BinaryReader::invalid_leading_byte_error(
+ x,
+ "component external kind",
+ offset,
+ ))
+ }
+ })
+ }
+}
+
+/// Represents an export in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub struct ComponentExport<'a> {
+ /// The name of the exported item.
+ pub name: &'a str,
+ /// The optional URL of the exported item.
+ pub url: &'a str,
+ /// The kind of the export.
+ pub kind: ComponentExternalKind,
+ /// The index of the exported item.
+ pub index: u32,
+ /// An optionally specified type ascribed to this export.
+ pub ty: Option<ComponentTypeRef>,
+}
+
+/// A reader for the export section of a WebAssembly component.
+pub type ComponentExportSectionReader<'a> = SectionLimited<'a, ComponentExport<'a>>;
+
+impl<'a> FromReader<'a> for ComponentExport<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(ComponentExport {
+ name: reader.read()?,
+ url: reader.read()?,
+ kind: reader.read()?,
+ index: reader.read()?,
+ ty: match reader.read_u8()? {
+ 0x00 => None,
+ 0x01 => Some(reader.read()?),
+ other => {
+ return Err(BinaryReader::invalid_leading_byte_error(
+ other,
+ "optional component export type",
+ reader.original_position() - 1,
+ ))
+ }
+ },
+ })
+ }
+}
+
+impl<'a> FromReader<'a> for ComponentExternalKind {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let offset = reader.original_position();
+ let byte1 = reader.read_u8()?;
+ let byte2 = if byte1 == 0x00 {
+ Some(reader.read_u8()?)
+ } else {
+ None
+ };
+
+ ComponentExternalKind::from_bytes(byte1, byte2, offset)
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/component/imports.rs b/third_party/rust/wasmparser/src/readers/component/imports.rs
new file mode 100644
index 0000000000..c1313c11e2
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/imports.rs
@@ -0,0 +1,109 @@
+use crate::{
+ BinaryReader, ComponentExternalKind, ComponentValType, FromReader, Result, SectionLimited,
+};
+
+/// Represents the type bounds for imports and exports.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum TypeBounds {
+ /// The type is bounded by equality.
+ Eq,
+}
+
+impl<'a> FromReader<'a> for TypeBounds {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x00 => TypeBounds::Eq,
+ x => return reader.invalid_leading_byte(x, "type bound"),
+ })
+ }
+}
+
+/// Represents a reference to a component type.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+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 a type index to an instance type.
+ Instance(u32),
+ /// The reference is to a component type.
+ ///
+ /// The index is a type index to a component type.
+ Component(u32),
+}
+
+impl ComponentTypeRef {
+ /// Returns the corresponding [`ComponentExternalKind`] for this reference.
+ pub fn kind(&self) -> ComponentExternalKind {
+ match self {
+ ComponentTypeRef::Module(_) => ComponentExternalKind::Module,
+ ComponentTypeRef::Func(_) => ComponentExternalKind::Func,
+ ComponentTypeRef::Value(_) => ComponentExternalKind::Value,
+ ComponentTypeRef::Type(..) => ComponentExternalKind::Type,
+ ComponentTypeRef::Instance(_) => ComponentExternalKind::Instance,
+ ComponentTypeRef::Component(_) => ComponentExternalKind::Component,
+ }
+ }
+}
+
+impl<'a> FromReader<'a> for ComponentTypeRef {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read()? {
+ ComponentExternalKind::Module => ComponentTypeRef::Module(reader.read()?),
+ ComponentExternalKind::Func => ComponentTypeRef::Func(reader.read()?),
+ ComponentExternalKind::Value => ComponentTypeRef::Value(reader.read()?),
+ ComponentExternalKind::Type => ComponentTypeRef::Type(reader.read()?, reader.read()?),
+ ComponentExternalKind::Instance => ComponentTypeRef::Instance(reader.read()?),
+ ComponentExternalKind::Component => ComponentTypeRef::Component(reader.read()?),
+ })
+ }
+}
+
+/// Represents an import in a WebAssembly component
+#[derive(Debug, Copy, Clone)]
+pub struct ComponentImport<'a> {
+ /// The name of the imported item.
+ pub name: &'a str,
+ /// The optional URL of the imported item.
+ pub url: &'a str,
+ /// The type reference for the import.
+ pub ty: ComponentTypeRef,
+}
+
+impl<'a> FromReader<'a> for ComponentImport<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(ComponentImport {
+ name: reader.read()?,
+ url: reader.read()?,
+ ty: reader.read()?,
+ })
+ }
+}
+
+/// A reader for the import section of a WebAssembly component.
+///
+/// # Examples
+///
+/// ```
+/// use wasmparser::ComponentImportSectionReader;
+/// let data: &[u8] = &[0x01, 0x01, 0x41, 0x00, 0x01, 0x66];
+/// let reader = ComponentImportSectionReader::new(data, 0).unwrap();
+/// for import in reader {
+/// let import = import.expect("import");
+/// println!("Import: {:?}", import);
+/// }
+/// ```
+pub type ComponentImportSectionReader<'a> = SectionLimited<'a, ComponentImport<'a>>;
diff --git a/third_party/rust/wasmparser/src/readers/component/instances.rs b/third_party/rust/wasmparser/src/readers/component/instances.rs
new file mode 100644
index 0000000000..8166395edc
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/instances.rs
@@ -0,0 +1,164 @@
+use crate::limits::{MAX_WASM_INSTANTIATION_ARGS, MAX_WASM_INSTANTIATION_EXPORTS};
+use crate::{
+ BinaryReader, ComponentExport, ComponentExternalKind, Export, FromReader, Result,
+ SectionLimited,
+};
+
+/// Represents the kind of an instantiation argument for a core instance.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum InstantiationArgKind {
+ /// The instantiation argument is a core instance.
+ Instance,
+}
+
+/// Represents an argument to instantiating a WebAssembly module.
+#[derive(Debug, Clone)]
+pub struct InstantiationArg<'a> {
+ /// The name of the module argument.
+ pub name: &'a str,
+ /// The kind of the module argument.
+ pub kind: InstantiationArgKind,
+ /// The index of the argument item.
+ pub index: u32,
+}
+
+/// Represents an instance of a WebAssembly module.
+#[derive(Debug, Clone)]
+pub enum Instance<'a> {
+ /// The instance is from instantiating a WebAssembly module.
+ Instantiate {
+ /// The module index.
+ module_index: u32,
+ /// The module's instantiation arguments.
+ args: Box<[InstantiationArg<'a>]>,
+ },
+ /// The instance is a from exporting local items.
+ FromExports(Box<[Export<'a>]>),
+}
+
+/// A reader for the core instance section of a WebAssembly component.
+///
+/// # Examples
+///
+/// ```
+/// use wasmparser::InstanceSectionReader;
+/// # let data: &[u8] = &[0x01, 0x00, 0x00, 0x01, 0x03, b'f', b'o', b'o', 0x12, 0x00];
+/// let mut reader = InstanceSectionReader::new(data, 0).unwrap();
+/// for inst in reader {
+/// println!("Instance {:?}", inst.expect("instance"));
+/// }
+/// ```
+pub type InstanceSectionReader<'a> = SectionLimited<'a, Instance<'a>>;
+
+impl<'a> FromReader<'a> for Instance<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x00 => Instance::Instantiate {
+ module_index: reader.read_var_u32()?,
+ args: reader
+ .read_iter(MAX_WASM_INSTANTIATION_ARGS, "core instantiation arguments")?
+ .collect::<Result<_>>()?,
+ },
+ 0x01 => Instance::FromExports(
+ reader
+ .read_iter(MAX_WASM_INSTANTIATION_ARGS, "core instantiation arguments")?
+ .collect::<Result<_>>()?,
+ ),
+ x => return reader.invalid_leading_byte(x, "core instance"),
+ })
+ }
+}
+
+impl<'a> FromReader<'a> for InstantiationArg<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(InstantiationArg {
+ name: reader.read()?,
+ kind: reader.read()?,
+ index: reader.read()?,
+ })
+ }
+}
+
+impl<'a> FromReader<'a> for InstantiationArgKind {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x12 => InstantiationArgKind::Instance,
+ x => return reader.invalid_leading_byte(x, "instantiation arg kind"),
+ })
+ }
+}
+
+/// Represents an argument to instantiating a WebAssembly component.
+#[derive(Debug, Clone)]
+pub struct ComponentInstantiationArg<'a> {
+ /// The name of the component argument.
+ pub name: &'a str,
+ /// The kind of the component argument.
+ pub kind: ComponentExternalKind,
+ /// The index of the argument item.
+ pub index: u32,
+}
+
+/// Represents an instance in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub enum ComponentInstance<'a> {
+ /// The instance is from instantiating a WebAssembly component.
+ Instantiate {
+ /// The component index.
+ component_index: u32,
+ /// The component's instantiation arguments.
+ args: Box<[ComponentInstantiationArg<'a>]>,
+ },
+ /// The instance is a from exporting local items.
+ FromExports(Box<[ComponentExport<'a>]>),
+}
+
+/// A reader for the component instance section of a WebAssembly component.
+///
+/// # Examples
+///
+/// ```
+/// use wasmparser::ComponentInstanceSectionReader;
+/// # let data: &[u8] = &[0x01, 0x00, 0x00, 0x01, 0x03, b'f', b'o', b'o', 0x01, 0x00];
+/// let mut reader = ComponentInstanceSectionReader::new(data, 0).unwrap();
+/// for inst in reader {
+/// println!("Instance {:?}", inst.expect("instance"));
+/// }
+/// ```
+pub type ComponentInstanceSectionReader<'a> = SectionLimited<'a, ComponentInstance<'a>>;
+
+impl<'a> FromReader<'a> for ComponentInstance<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x00 => ComponentInstance::Instantiate {
+ component_index: reader.read_var_u32()?,
+ args: reader
+ .read_iter(MAX_WASM_INSTANTIATION_ARGS, "instantiation arguments")?
+ .collect::<Result<_>>()?,
+ },
+ 0x01 => ComponentInstance::FromExports(
+ (0..reader.read_size(MAX_WASM_INSTANTIATION_EXPORTS, "instantiation exports")?)
+ .map(|_| {
+ Ok(ComponentExport {
+ name: reader.read()?,
+ url: "",
+ kind: reader.read()?,
+ index: reader.read()?,
+ ty: None,
+ })
+ })
+ .collect::<Result<_>>()?,
+ ),
+ x => return reader.invalid_leading_byte(x, "instance"),
+ })
+ }
+}
+impl<'a> FromReader<'a> for ComponentInstantiationArg<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(ComponentInstantiationArg {
+ name: reader.read()?,
+ kind: reader.read()?,
+ index: reader.read()?,
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/component/names.rs b/third_party/rust/wasmparser/src/readers/component/names.rs
new file mode 100644
index 0000000000..19de2752d0
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/names.rs
@@ -0,0 +1,102 @@
+use crate::{BinaryReader, BinaryReaderError, NameMap, Result, Subsection, Subsections};
+use std::ops::Range;
+
+/// Type used to iterate and parse the contents of the `component-name` custom
+/// section in compnents, similar to the `name` section of core modules.
+pub type ComponentNameSectionReader<'a> = Subsections<'a, ComponentName<'a>>;
+
+/// Represents a name read from the names custom section.
+#[derive(Clone)]
+#[allow(missing_docs)]
+pub enum ComponentName<'a> {
+ Component {
+ name: &'a str,
+ name_range: Range<usize>,
+ },
+ CoreFuncs(NameMap<'a>),
+ CoreGlobals(NameMap<'a>),
+ CoreMemories(NameMap<'a>),
+ CoreTables(NameMap<'a>),
+ CoreModules(NameMap<'a>),
+ CoreInstances(NameMap<'a>),
+ CoreTypes(NameMap<'a>),
+ Types(NameMap<'a>),
+ Instances(NameMap<'a>),
+ Components(NameMap<'a>),
+ Funcs(NameMap<'a>),
+ Values(NameMap<'a>),
+
+ /// An unknown [name subsection](https://webassembly.github.io/spec/core/appendix/custom.html#subsections).
+ Unknown {
+ /// The identifier for this subsection.
+ ty: u8,
+ /// The contents of this subsection.
+ data: &'a [u8],
+ /// The range of bytes, relative to the start of the original data
+ /// stream, that the contents of this subsection reside in.
+ range: Range<usize>,
+ },
+}
+
+impl<'a> Subsection<'a> for ComponentName<'a> {
+ fn from_reader(id: u8, mut reader: BinaryReader<'a>) -> Result<Self> {
+ let data = reader.remaining_buffer();
+ let offset = reader.original_position();
+ Ok(match id {
+ 0 => {
+ let name = reader.read_string()?;
+ if !reader.eof() {
+ return Err(BinaryReaderError::new(
+ "trailing data at the end of a name",
+ reader.original_position(),
+ ));
+ }
+ ComponentName::Component {
+ name,
+ name_range: offset..offset + reader.position,
+ }
+ }
+ 1 => {
+ let ctor: fn(NameMap<'a>) -> ComponentName<'a> = match reader.read_u8()? {
+ 0x00 => match reader.read_u8()? {
+ 0x00 => ComponentName::CoreFuncs,
+ 0x01 => ComponentName::CoreTables,
+ 0x02 => ComponentName::CoreMemories,
+ 0x03 => ComponentName::CoreGlobals,
+ 0x10 => ComponentName::CoreTypes,
+ 0x11 => ComponentName::CoreModules,
+ 0x12 => ComponentName::CoreInstances,
+ _ => {
+ return Ok(ComponentName::Unknown {
+ ty: 1,
+ data,
+ range: offset..offset + data.len(),
+ });
+ }
+ },
+ 0x01 => ComponentName::Funcs,
+ 0x02 => ComponentName::Values,
+ 0x03 => ComponentName::Types,
+ 0x04 => ComponentName::Components,
+ 0x05 => ComponentName::Instances,
+ _ => {
+ return Ok(ComponentName::Unknown {
+ ty: 1,
+ data,
+ range: offset..offset + data.len(),
+ });
+ }
+ };
+ ctor(NameMap::new(
+ reader.remaining_buffer(),
+ reader.original_position(),
+ )?)
+ }
+ ty => ComponentName::Unknown {
+ ty,
+ data,
+ range: offset..offset + data.len(),
+ },
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/component/start.rs b/third_party/rust/wasmparser/src/readers/component/start.rs
new file mode 100644
index 0000000000..dc01fa4340
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/start.rs
@@ -0,0 +1,30 @@
+use crate::limits::{MAX_WASM_FUNCTION_RETURNS, MAX_WASM_START_ARGS};
+use crate::{BinaryReader, FromReader, Result};
+
+/// Represents the start function in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub struct ComponentStartFunction {
+ /// The index to the start function.
+ pub func_index: u32,
+ /// The start function arguments.
+ ///
+ /// The arguments are specified by value index.
+ pub arguments: Box<[u32]>,
+ /// The number of expected results for the start function.
+ pub results: u32,
+}
+
+impl<'a> FromReader<'a> for ComponentStartFunction {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let func_index = reader.read_var_u32()?;
+ let arguments = reader
+ .read_iter(MAX_WASM_START_ARGS, "start function arguments")?
+ .collect::<Result<_>>()?;
+ let results = reader.read_size(MAX_WASM_FUNCTION_RETURNS, "start function results")? as u32;
+ Ok(ComponentStartFunction {
+ func_index,
+ arguments,
+ results,
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/component/types.rs b/third_party/rust/wasmparser/src/readers/component/types.rs
new file mode 100644
index 0000000000..b0e9687a4d
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/types.rs
@@ -0,0 +1,508 @@
+use crate::limits::*;
+use crate::{
+ BinaryReader, ComponentAlias, ComponentImport, ComponentTypeRef, FromReader, FuncType, Import,
+ Result, SectionLimited, Type, TypeRef,
+};
+
+/// Represents the kind of an outer core alias in a WebAssembly component.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum OuterAliasKind {
+ /// The alias is to a core type.
+ Type,
+}
+
+/// Represents a core type in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub enum CoreType<'a> {
+ /// The type is for a core function.
+ Func(FuncType),
+ /// The type is for a core module.
+ Module(Box<[ModuleTypeDeclaration<'a>]>),
+}
+
+impl<'a> FromReader<'a> for CoreType<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x60 => CoreType::Func(reader.read()?),
+ 0x50 => CoreType::Module(
+ reader
+ .read_iter(MAX_WASM_MODULE_TYPE_DECLS, "module type declaration")?
+ .collect::<Result<_>>()?,
+ ),
+ x => return reader.invalid_leading_byte(x, "core type"),
+ })
+ }
+}
+
+/// Represents a module type declaration in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub enum ModuleTypeDeclaration<'a> {
+ /// The module type definition is for a type.
+ Type(Type),
+ /// The module type definition is for an export.
+ Export {
+ /// The name of the exported item.
+ name: &'a str,
+ /// The type reference of the export.
+ ty: TypeRef,
+ },
+ /// The module type declaration is for an outer alias.
+ OuterAlias {
+ /// The alias kind.
+ kind: OuterAliasKind,
+ /// The outward count, starting at zero for the current type.
+ count: u32,
+ /// The index of the item within the outer type.
+ index: u32,
+ },
+ /// The module type definition is for an import.
+ Import(Import<'a>),
+}
+
+impl<'a> FromReader<'a> for ModuleTypeDeclaration<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x00 => ModuleTypeDeclaration::Import(reader.read()?),
+ 0x01 => ModuleTypeDeclaration::Type(reader.read()?),
+ 0x02 => {
+ let kind = match reader.read_u8()? {
+ 0x10 => OuterAliasKind::Type,
+ x => {
+ return reader.invalid_leading_byte(x, "outer alias kind");
+ }
+ };
+ match reader.read_u8()? {
+ 0x01 => ModuleTypeDeclaration::OuterAlias {
+ kind,
+ count: reader.read()?,
+ index: reader.read()?,
+ },
+ x => {
+ return reader.invalid_leading_byte(x, "outer alias target");
+ }
+ }
+ }
+ 0x03 => ModuleTypeDeclaration::Export {
+ name: reader.read()?,
+ ty: reader.read()?,
+ },
+ x => return reader.invalid_leading_byte(x, "type definition"),
+ })
+ }
+}
+
+/// A reader for the core type section of a WebAssembly component.
+///
+/// # Examples
+/// ```
+/// use wasmparser::CoreTypeSectionReader;
+/// # let data: &[u8] = &[0x01, 0x60, 0x00, 0x00];
+/// let mut reader = CoreTypeSectionReader::new(data, 0).unwrap();
+/// for ty in reader {
+/// println!("Type {:?}", ty.expect("type"));
+/// }
+/// ```
+pub type CoreTypeSectionReader<'a> = SectionLimited<'a, CoreType<'a>>;
+
+/// Represents a value type in a WebAssembly component.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum ComponentValType {
+ /// The value type is a primitive type.
+ Primitive(PrimitiveValType),
+ /// The value type is a reference to a defined type.
+ Type(u32),
+}
+
+impl<'a> FromReader<'a> for ComponentValType {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ if let Some(ty) = PrimitiveValType::from_byte(reader.peek()?) {
+ reader.position += 1;
+ return Ok(ComponentValType::Primitive(ty));
+ }
+
+ Ok(ComponentValType::Type(reader.read_var_s33()? as u32))
+ }
+}
+
+impl<'a> FromReader<'a> for Option<ComponentValType> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ match reader.read_u8()? {
+ 0x0 => Ok(None),
+ 0x1 => Ok(Some(reader.read()?)),
+ x => reader.invalid_leading_byte(x, "optional component value type"),
+ }
+ }
+}
+
+/// Represents a primitive value type.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+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 PrimitiveValType {
+ fn from_byte(byte: u8) -> Option<PrimitiveValType> {
+ Some(match byte {
+ 0x7f => PrimitiveValType::Bool,
+ 0x7e => PrimitiveValType::S8,
+ 0x7d => PrimitiveValType::U8,
+ 0x7c => PrimitiveValType::S16,
+ 0x7b => PrimitiveValType::U16,
+ 0x7a => PrimitiveValType::S32,
+ 0x79 => PrimitiveValType::U32,
+ 0x78 => PrimitiveValType::S64,
+ 0x77 => PrimitiveValType::U64,
+ 0x76 => PrimitiveValType::Float32,
+ 0x75 => PrimitiveValType::Float64,
+ 0x74 => PrimitiveValType::Char,
+ 0x73 => PrimitiveValType::String,
+ _ => return None,
+ })
+ }
+
+ pub(crate) fn requires_realloc(&self) -> bool {
+ matches!(self, Self::String)
+ }
+
+ /// Determines if primitive value type `a` is a subtype of `b`.
+ pub fn is_subtype_of(a: Self, b: Self) -> bool {
+ // Note that this intentionally diverges from the upstream specification
+ // at this time and only considers exact equality for subtyping
+ // relationships.
+ //
+ // More information can be found in the subtyping implementation for
+ // component functions.
+ a == b
+ }
+}
+
+/// Represents a type in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub enum ComponentType<'a> {
+ /// The type is a component defined type.
+ Defined(ComponentDefinedType<'a>),
+ /// The type is a function type.
+ Func(ComponentFuncType<'a>),
+ /// The type is a component type.
+ Component(Box<[ComponentTypeDeclaration<'a>]>),
+ /// The type is an instance type.
+ Instance(Box<[InstanceTypeDeclaration<'a>]>),
+}
+
+impl<'a> FromReader<'a> for ComponentType<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x40 => {
+ let params = reader
+ .read_iter(MAX_WASM_FUNCTION_PARAMS, "component function parameters")?
+ .collect::<Result<_>>()?;
+ let results = reader.read()?;
+ ComponentType::Func(ComponentFuncType { params, results })
+ }
+ 0x41 => ComponentType::Component(
+ reader
+ .read_iter(MAX_WASM_COMPONENT_TYPE_DECLS, "component type declaration")?
+ .collect::<Result<_>>()?,
+ ),
+ 0x42 => ComponentType::Instance(
+ reader
+ .read_iter(MAX_WASM_INSTANCE_TYPE_DECLS, "instance type declaration")?
+ .collect::<Result<_>>()?,
+ ),
+ x => {
+ if let Some(ty) = PrimitiveValType::from_byte(x) {
+ ComponentType::Defined(ComponentDefinedType::Primitive(ty))
+ } else {
+ ComponentType::Defined(ComponentDefinedType::read(reader, x)?)
+ }
+ }
+ })
+ }
+}
+
+/// Represents part of a component type declaration in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub enum ComponentTypeDeclaration<'a> {
+ /// The component type declaration is for a core type.
+ CoreType(CoreType<'a>),
+ /// The component type declaration is for a type.
+ Type(ComponentType<'a>),
+ /// The component type declaration is for an alias.
+ Alias(ComponentAlias<'a>),
+ /// The component type declaration is for an export.
+ Export {
+ /// The name of the export.
+ name: &'a str,
+ /// The optional URL of the export.
+ url: &'a str,
+ /// The type reference for the export.
+ ty: ComponentTypeRef,
+ },
+ /// The component type declaration is for an import.
+ Import(ComponentImport<'a>),
+}
+
+impl<'a> FromReader<'a> for ComponentTypeDeclaration<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ // Component types are effectively instance types with the additional
+ // variant of imports; check for imports here or delegate to
+ // `InstanceTypeDeclaration` with the appropriate conversions.
+ if reader.peek()? == 0x03 {
+ reader.position += 1;
+ return Ok(ComponentTypeDeclaration::Import(reader.read()?));
+ }
+
+ Ok(match reader.read()? {
+ InstanceTypeDeclaration::CoreType(t) => ComponentTypeDeclaration::CoreType(t),
+ InstanceTypeDeclaration::Type(t) => ComponentTypeDeclaration::Type(t),
+ InstanceTypeDeclaration::Alias(a) => ComponentTypeDeclaration::Alias(a),
+ InstanceTypeDeclaration::Export { name, url, ty } => {
+ ComponentTypeDeclaration::Export { name, url, ty }
+ }
+ })
+ }
+}
+
+/// Represents an instance type declaration in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub enum InstanceTypeDeclaration<'a> {
+ /// The component type declaration is for a core type.
+ CoreType(CoreType<'a>),
+ /// The instance type declaration is for a type.
+ Type(ComponentType<'a>),
+ /// The instance type declaration is for an alias.
+ Alias(ComponentAlias<'a>),
+ /// The instance type declaration is for an export.
+ Export {
+ /// The name of the export.
+ name: &'a str,
+ /// The URL for the export.
+ url: &'a str,
+ /// The type reference for the export.
+ ty: ComponentTypeRef,
+ },
+}
+
+impl<'a> FromReader<'a> for InstanceTypeDeclaration<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x00 => InstanceTypeDeclaration::CoreType(reader.read()?),
+ 0x01 => InstanceTypeDeclaration::Type(reader.read()?),
+ 0x02 => InstanceTypeDeclaration::Alias(reader.read()?),
+ 0x04 => InstanceTypeDeclaration::Export {
+ name: reader.read()?,
+ url: reader.read()?,
+ ty: reader.read()?,
+ },
+ x => return reader.invalid_leading_byte(x, "component or instance type declaration"),
+ })
+ }
+}
+
+/// Represents the result type of a component function.
+#[derive(Debug, Clone)]
+pub enum ComponentFuncResult<'a> {
+ /// The function returns a singular, unnamed type.
+ Unnamed(ComponentValType),
+ /// The function returns zero or more named types.
+ Named(Box<[(&'a str, ComponentValType)]>),
+}
+
+impl<'a> FromReader<'a> for ComponentFuncResult<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x00 => ComponentFuncResult::Unnamed(reader.read()?),
+ 0x01 => ComponentFuncResult::Named(
+ reader
+ .read_iter(MAX_WASM_FUNCTION_RETURNS, "component function results")?
+ .collect::<Result<_>>()?,
+ ),
+ x => return reader.invalid_leading_byte(x, "component function results"),
+ })
+ }
+}
+
+impl ComponentFuncResult<'_> {
+ /// Gets the count of types returned by the function.
+ pub fn type_count(&self) -> usize {
+ match self {
+ Self::Unnamed(_) => 1,
+ Self::Named(vec) => vec.len(),
+ }
+ }
+
+ /// Iterates over the types returned by the function.
+ pub fn iter(&self) -> impl Iterator<Item = (Option<&str>, &ComponentValType)> {
+ enum Either<L, R> {
+ Left(L),
+ Right(R),
+ }
+
+ impl<L, R> Iterator for Either<L, R>
+ where
+ L: Iterator,
+ R: Iterator<Item = L::Item>,
+ {
+ type Item = L::Item;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match self {
+ Either::Left(l) => l.next(),
+ Either::Right(r) => r.next(),
+ }
+ }
+ }
+
+ match self {
+ Self::Unnamed(ty) => Either::Left(std::iter::once(ty).map(|ty| (None, ty))),
+ Self::Named(vec) => Either::Right(vec.iter().map(|(n, ty)| (Some(*n), ty))),
+ }
+ }
+}
+
+/// Represents a type of a function in a WebAssembly component.
+#[derive(Debug, Clone)]
+pub struct ComponentFuncType<'a> {
+ /// The function parameters.
+ pub params: Box<[(&'a str, ComponentValType)]>,
+ /// The function result.
+ pub results: ComponentFuncResult<'a>,
+}
+
+/// Represents a case in a variant type.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct VariantCase<'a> {
+ /// The name of the variant case.
+ pub name: &'a str,
+ /// The value type of the variant case.
+ pub ty: Option<ComponentValType>,
+ /// The index of the variant case that is refined by this one.
+ pub refines: Option<u32>,
+}
+
+impl<'a> FromReader<'a> for VariantCase<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(VariantCase {
+ name: reader.read()?,
+ ty: reader.read()?,
+ refines: match reader.read_u8()? {
+ 0x0 => None,
+ 0x1 => Some(reader.read_var_u32()?),
+ x => return reader.invalid_leading_byte(x, "variant case refines"),
+ },
+ })
+ }
+}
+
+/// Represents a defined type in a WebAssembly component.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum ComponentDefinedType<'a> {
+ /// The type is one of the primitive value types.
+ Primitive(PrimitiveValType),
+ /// The type is a record with the given fields.
+ Record(Box<[(&'a str, ComponentValType)]>),
+ /// The type is a variant with the given cases.
+ Variant(Box<[VariantCase<'a>]>),
+ /// The type is a list of the given value type.
+ List(ComponentValType),
+ /// The type is a tuple of the given value types.
+ Tuple(Box<[ComponentValType]>),
+ /// The type is flags with the given names.
+ Flags(Box<[&'a str]>),
+ /// The type is an enum with the given tags.
+ Enum(Box<[&'a str]>),
+ /// The type is a union of the given value types.
+ Union(Box<[ComponentValType]>),
+ /// The type is an option of the given value type.
+ Option(ComponentValType),
+ /// The type is a result type.
+ Result {
+ /// The type returned for success.
+ ok: Option<ComponentValType>,
+ /// The type returned for failure.
+ err: Option<ComponentValType>,
+ },
+}
+
+impl<'a> ComponentDefinedType<'a> {
+ fn read(reader: &mut BinaryReader<'a>, byte: u8) -> Result<ComponentDefinedType<'a>> {
+ Ok(match byte {
+ 0x72 => ComponentDefinedType::Record(
+ reader
+ .read_iter(MAX_WASM_RECORD_FIELDS, "record field")?
+ .collect::<Result<_>>()?,
+ ),
+ 0x71 => ComponentDefinedType::Variant(
+ reader
+ .read_iter(MAX_WASM_VARIANT_CASES, "variant cases")?
+ .collect::<Result<_>>()?,
+ ),
+ 0x70 => ComponentDefinedType::List(reader.read()?),
+ 0x6f => ComponentDefinedType::Tuple(
+ reader
+ .read_iter(MAX_WASM_TUPLE_TYPES, "tuple types")?
+ .collect::<Result<_>>()?,
+ ),
+ 0x6e => ComponentDefinedType::Flags(
+ reader
+ .read_iter(MAX_WASM_FLAG_NAMES, "flag names")?
+ .collect::<Result<_>>()?,
+ ),
+ 0x6d => ComponentDefinedType::Enum(
+ reader
+ .read_iter(MAX_WASM_ENUM_CASES, "enum cases")?
+ .collect::<Result<_>>()?,
+ ),
+ 0x6c => ComponentDefinedType::Union(
+ reader
+ .read_iter(MAX_WASM_UNION_TYPES, "union types")?
+ .collect::<Result<_>>()?,
+ ),
+ 0x6b => ComponentDefinedType::Option(reader.read()?),
+ 0x6a => ComponentDefinedType::Result {
+ ok: reader.read()?,
+ err: reader.read()?,
+ },
+ x => return reader.invalid_leading_byte(x, "component defined type"),
+ })
+ }
+}
+
+/// A reader for the type section of a WebAssembly component.
+///
+/// # Examples
+///
+/// ```
+/// use wasmparser::ComponentTypeSectionReader;
+/// let data: &[u8] = &[0x01, 0x40, 0x01, 0x03, b'f', b'o', b'o', 0x73, 0x00, 0x73];
+/// let mut reader = ComponentTypeSectionReader::new(data, 0).unwrap();
+/// for ty in reader {
+/// println!("Type {:?}", ty.expect("type"));
+/// }
+/// ```
+pub type ComponentTypeSectionReader<'a> = SectionLimited<'a, ComponentType<'a>>;