summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wasmparser/src/readers
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wasmparser/src/readers')
-rw-r--r--third_party/rust/wasmparser/src/readers/component.rs17
-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
-rw-r--r--third_party/rust/wasmparser/src/readers/core.rs33
-rw-r--r--third_party/rust/wasmparser/src/readers/core/code.rs146
-rw-r--r--third_party/rust/wasmparser/src/readers/core/custom.rs63
-rw-r--r--third_party/rust/wasmparser/src/readers/core/data.rs96
-rw-r--r--third_party/rust/wasmparser/src/readers/core/elements.rs158
-rw-r--r--third_party/rust/wasmparser/src/readers/core/exports.rs65
-rw-r--r--third_party/rust/wasmparser/src/readers/core/functions.rs17
-rw-r--r--third_party/rust/wasmparser/src/readers/core/globals.rs49
-rw-r--r--third_party/rust/wasmparser/src/readers/core/imports.rs76
-rw-r--r--third_party/rust/wasmparser/src/readers/core/init.rs51
-rw-r--r--third_party/rust/wasmparser/src/readers/core/memories.rs56
-rw-r--r--third_party/rust/wasmparser/src/readers/core/names.rs153
-rw-r--r--third_party/rust/wasmparser/src/readers/core/operators.rs354
-rw-r--r--third_party/rust/wasmparser/src/readers/core/producers.rs78
-rw-r--r--third_party/rust/wasmparser/src/readers/core/tables.rs87
-rw-r--r--third_party/rust/wasmparser/src/readers/core/tags.rs32
-rw-r--r--third_party/rust/wasmparser/src/readers/core/types.rs380
26 files changed, 3143 insertions, 0 deletions
diff --git a/third_party/rust/wasmparser/src/readers/component.rs b/third_party/rust/wasmparser/src/readers/component.rs
new file mode 100644
index 0000000000..24b490d0c3
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component.rs
@@ -0,0 +1,17 @@
+mod aliases;
+mod canonicals;
+mod exports;
+mod imports;
+mod instances;
+mod names;
+mod start;
+mod types;
+
+pub use self::aliases::*;
+pub use self::canonicals::*;
+pub use self::exports::*;
+pub use self::imports::*;
+pub use self::instances::*;
+pub use self::names::*;
+pub use self::start::*;
+pub use self::types::*;
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>>;
diff --git a/third_party/rust/wasmparser/src/readers/core.rs b/third_party/rust/wasmparser/src/readers/core.rs
new file mode 100644
index 0000000000..c42bbf8d9e
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core.rs
@@ -0,0 +1,33 @@
+mod code;
+mod custom;
+mod data;
+mod elements;
+mod exports;
+mod functions;
+mod globals;
+mod imports;
+mod init;
+mod memories;
+mod names;
+mod operators;
+mod producers;
+mod tables;
+mod tags;
+mod types;
+
+pub use self::code::*;
+pub use self::custom::*;
+pub use self::data::*;
+pub use self::elements::*;
+pub use self::exports::*;
+pub use self::functions::*;
+pub use self::globals::*;
+pub use self::imports::*;
+pub use self::init::*;
+pub use self::memories::*;
+pub use self::names::*;
+pub use self::operators::*;
+pub use self::producers::*;
+pub use self::tables::*;
+pub use self::tags::*;
+pub use self::types::*;
diff --git a/third_party/rust/wasmparser/src/readers/core/code.rs b/third_party/rust/wasmparser/src/readers/core/code.rs
new file mode 100644
index 0000000000..2a463727e8
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/code.rs
@@ -0,0 +1,146 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, FromReader, OperatorsReader, Result, SectionLimited, ValType};
+use std::ops::Range;
+
+/// A reader for the code section of a WebAssembly module.
+pub type CodeSectionReader<'a> = SectionLimited<'a, FunctionBody<'a>>;
+
+/// Represents a WebAssembly function body.
+#[derive(Debug, Clone)]
+pub struct FunctionBody<'a> {
+ reader: BinaryReader<'a>,
+}
+
+impl<'a> FunctionBody<'a> {
+ /// Constructs a new `FunctionBody` for the given data and offset.
+ pub fn new(offset: usize, data: &'a [u8]) -> Self {
+ Self {
+ reader: BinaryReader::new_with_offset(data, offset),
+ }
+ }
+
+ /// Whether or not to allow 64-bit memory arguments in the
+ /// function body.
+ ///
+ /// This is intended to be `true` when support for the memory64
+ /// WebAssembly proposal is also enabled.
+ pub fn allow_memarg64(&mut self, allow: bool) {
+ self.reader.allow_memarg64(allow);
+ }
+
+ /// Gets a binary reader for this function body.
+ pub fn get_binary_reader(&self) -> BinaryReader<'a> {
+ self.reader.clone()
+ }
+
+ fn skip_locals(reader: &mut BinaryReader) -> Result<()> {
+ let count = reader.read_var_u32()?;
+ for _ in 0..count {
+ reader.read_var_u32()?;
+ reader.read::<ValType>()?;
+ }
+ Ok(())
+ }
+
+ /// Gets the locals reader for this function body.
+ pub fn get_locals_reader(&self) -> Result<LocalsReader<'a>> {
+ let mut reader = self.reader.clone();
+ let count = reader.read_var_u32()?;
+ Ok(LocalsReader { reader, count })
+ }
+
+ /// Gets the operators reader for this function body.
+ pub fn get_operators_reader(&self) -> Result<OperatorsReader<'a>> {
+ let mut reader = self.reader.clone();
+ Self::skip_locals(&mut reader)?;
+ Ok(OperatorsReader::new(reader))
+ }
+
+ /// Gets the range of the function body.
+ pub fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> FromReader<'a> for FunctionBody<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let reader = reader.read_reader("function body extends past end of the code section")?;
+ Ok(FunctionBody { reader })
+ }
+}
+
+/// A reader for a function body's locals.
+pub struct LocalsReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> LocalsReader<'a> {
+ /// Gets the count of locals in the function body.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Gets the original position of the reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Reads an item from the reader.
+ pub fn read(&mut self) -> Result<(u32, ValType)> {
+ let count = self.reader.read()?;
+ let value_type = self.reader.read()?;
+ Ok((count, value_type))
+ }
+}
+
+impl<'a> IntoIterator for LocalsReader<'a> {
+ type Item = Result<(u32, ValType)>;
+ type IntoIter = LocalsIterator<'a>;
+ fn into_iter(self) -> Self::IntoIter {
+ let count = self.count;
+ LocalsIterator {
+ reader: self,
+ left: count,
+ err: false,
+ }
+ }
+}
+
+/// An iterator over locals in a function body.
+pub struct LocalsIterator<'a> {
+ reader: LocalsReader<'a>,
+ left: u32,
+ err: bool,
+}
+
+impl<'a> Iterator for LocalsIterator<'a> {
+ type Item = Result<(u32, ValType)>;
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.err || self.left == 0 {
+ return None;
+ }
+ let result = self.reader.read();
+ self.err = result.is_err();
+ self.left -= 1;
+ Some(result)
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let count = self.reader.get_count() as usize;
+ (count, Some(count))
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/custom.rs b/third_party/rust/wasmparser/src/readers/core/custom.rs
new file mode 100644
index 0000000000..a04fe5a1ac
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/custom.rs
@@ -0,0 +1,63 @@
+use crate::{BinaryReader, Result};
+use std::ops::Range;
+
+/// A reader for custom sections of a WebAssembly module.
+#[derive(Clone)]
+pub struct CustomSectionReader<'a> {
+ // NB: these fields are public to the crate to make testing easier.
+ pub(crate) name: &'a str,
+ pub(crate) data_offset: usize,
+ pub(crate) data: &'a [u8],
+ pub(crate) range: Range<usize>,
+}
+
+impl<'a> CustomSectionReader<'a> {
+ /// Constructs a new `CustomSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<CustomSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let name = reader.read_string()?;
+ let data_offset = reader.original_position();
+ let data = reader.remaining_buffer();
+ let range = reader.range();
+ Ok(CustomSectionReader {
+ name,
+ data_offset,
+ data,
+ range,
+ })
+ }
+
+ /// The name of the custom section.
+ pub fn name(&self) -> &'a str {
+ self.name
+ }
+
+ /// The offset, relative to the start of the original module or component,
+ /// that the `data` payload for this custom section starts at.
+ pub fn data_offset(&self) -> usize {
+ self.data_offset
+ }
+
+ /// The actual contents of the custom section.
+ pub fn data(&self) -> &'a [u8] {
+ self.data
+ }
+
+ /// The range of bytes that specify this whole custom section (including
+ /// both the name of this custom section and its data) specified in
+ /// offsets relative to the start of the byte stream.
+ pub fn range(&self) -> Range<usize> {
+ self.range.clone()
+ }
+}
+
+impl<'a> std::fmt::Debug for CustomSectionReader<'a> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("CustomSectionReader")
+ .field("name", &self.name)
+ .field("data_offset", &self.data_offset)
+ .field("data", &"...")
+ .field("range", &self.range)
+ .finish()
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/data.rs b/third_party/rust/wasmparser/src/readers/core/data.rs
new file mode 100644
index 0000000000..5ea5f99457
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/data.rs
@@ -0,0 +1,96 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, BinaryReaderError, ConstExpr, FromReader, Result, SectionLimited};
+use std::ops::Range;
+
+/// Represents a data segment in a core WebAssembly module.
+#[derive(Debug, Clone)]
+pub struct Data<'a> {
+ /// The kind of data segment.
+ pub kind: DataKind<'a>,
+ /// The data of the data segment.
+ pub data: &'a [u8],
+ /// The range of the data segment.
+ pub range: Range<usize>,
+}
+
+/// The kind of data segment.
+#[derive(Debug, Copy, Clone)]
+pub enum DataKind<'a> {
+ /// The data segment is passive.
+ Passive,
+ /// The data segment is active.
+ Active {
+ /// The memory index for the data segment.
+ memory_index: u32,
+ /// The initialization expression for the data segment.
+ offset_expr: ConstExpr<'a>,
+ },
+}
+
+/// A reader for the data section of a WebAssembly module.
+pub type DataSectionReader<'a> = SectionLimited<'a, Data<'a>>;
+
+impl<'a> FromReader<'a> for Data<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let segment_start = reader.original_position();
+
+ // The current handling of the flags is largely specified in the `bulk-memory` proposal,
+ // which at the time this comment is written has been merged to the main specification
+ // draft.
+ //
+ // Notably, this proposal allows multiple different encodings of the memory index 0. `00`
+ // and `02 00` are both valid ways to specify the 0-th memory. However it also makes
+ // another encoding of the 0-th memory `80 00` no longer valid.
+ //
+ // We, however maintain this by parsing `flags` as a LEB128 integer. In that case, `80 00`
+ // encoding is parsed out as `0` and is therefore assigned a `memidx` 0, even though the
+ // current specification draft does not allow for this.
+ //
+ // See also https://github.com/WebAssembly/spec/issues/1439
+ let flags = reader.read_var_u32()?;
+ let kind = match flags {
+ 1 => DataKind::Passive,
+ 0 | 2 => {
+ let memory_index = if flags == 0 {
+ 0
+ } else {
+ reader.read_var_u32()?
+ };
+ let offset_expr = reader.read()?;
+ DataKind::Active {
+ memory_index,
+ offset_expr,
+ }
+ }
+ _ => {
+ return Err(BinaryReaderError::new(
+ "invalid flags byte in data segment",
+ segment_start,
+ ));
+ }
+ };
+
+ let data = reader.read_reader(
+ "unexpected end of section or function: data segment extends past end of the section",
+ )?;
+ Ok(Data {
+ kind,
+ data: data.remaining_buffer(),
+ range: segment_start..data.range().end,
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/elements.rs b/third_party/rust/wasmparser/src/readers/core/elements.rs
new file mode 100644
index 0000000000..7e37e7d7b6
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/elements.rs
@@ -0,0 +1,158 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{
+ BinaryReader, BinaryReaderError, ConstExpr, ExternalKind, FromReader, RefType, Result,
+ SectionLimited,
+};
+use std::ops::Range;
+
+/// Represents a core WebAssembly element segment.
+#[derive(Clone)]
+pub struct Element<'a> {
+ /// The kind of the element segment.
+ pub kind: ElementKind<'a>,
+ /// The initial elements of the element segment.
+ pub items: ElementItems<'a>,
+ /// The type of the elements.
+ pub ty: RefType,
+ /// The range of the the element segment.
+ pub range: Range<usize>,
+}
+
+/// The kind of element segment.
+#[derive(Clone)]
+pub enum ElementKind<'a> {
+ /// The element segment is passive.
+ Passive,
+ /// The element segment is active.
+ Active {
+ /// The index of the table being initialized.
+ table_index: u32,
+ /// The initial expression of the element segment.
+ offset_expr: ConstExpr<'a>,
+ },
+ /// The element segment is declared.
+ Declared,
+}
+
+/// Represents the items of an element segment.
+#[derive(Clone)]
+pub enum ElementItems<'a> {
+ /// This element contains function indices.
+ Functions(SectionLimited<'a, u32>),
+ /// This element contains constant expressions used to initialize the table.
+ Expressions(SectionLimited<'a, ConstExpr<'a>>),
+}
+
+/// A reader for the element section of a WebAssembly module.
+pub type ElementSectionReader<'a> = SectionLimited<'a, Element<'a>>;
+
+impl<'a> FromReader<'a> for Element<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let elem_start = reader.original_position();
+ // The current handling of the flags is largely specified in the `bulk-memory` proposal,
+ // which at the time this commend is written has been merged to the main specification
+ // draft.
+ //
+ // Notably, this proposal allows multiple different encodings of the table index 0. `00`
+ // and `02 00` are both valid ways to specify the 0-th table. However it also makes
+ // another encoding of the 0-th memory `80 00` no longer valid.
+ //
+ // We, however maintain this support by parsing `flags` as a LEB128 integer. In that case,
+ // `80 00` encoding is parsed out as `0` and is therefore assigned a `tableidx` 0, even
+ // though the current specification draft does not allow for this.
+ //
+ // See also https://github.com/WebAssembly/spec/issues/1439
+ let flags = reader.read_var_u32()?;
+ if (flags & !0b111) != 0 {
+ return Err(BinaryReaderError::new(
+ "invalid flags byte in element segment",
+ reader.original_position() - 1,
+ ));
+ }
+ let kind = if flags & 0b001 != 0 {
+ if flags & 0b010 != 0 {
+ ElementKind::Declared
+ } else {
+ ElementKind::Passive
+ }
+ } else {
+ let table_index = if flags & 0b010 == 0 {
+ 0
+ } else {
+ reader.read_var_u32()?
+ };
+ let offset_expr = reader.read()?;
+ ElementKind::Active {
+ table_index,
+ offset_expr,
+ }
+ };
+ let exprs = flags & 0b100 != 0;
+ let ty = if flags & 0b011 != 0 {
+ if exprs {
+ reader.read()?
+ } else {
+ match reader.read()? {
+ ExternalKind::Func => RefType::FUNCREF,
+ _ => {
+ return Err(BinaryReaderError::new(
+ "only the function external type is supported in elem segment",
+ reader.original_position() - 1,
+ ));
+ }
+ }
+ }
+ } else {
+ RefType::FUNCREF
+ };
+ // FIXME(#188) ideally wouldn't have to do skips here
+ let data = reader.skip(|reader| {
+ let items_count = reader.read_var_u32()?;
+ if exprs {
+ for _ in 0..items_count {
+ reader.skip_const_expr()?;
+ }
+ } else {
+ for _ in 0..items_count {
+ reader.read_var_u32()?;
+ }
+ }
+ Ok(())
+ })?;
+ let items = if exprs {
+ ElementItems::Expressions(SectionLimited::new(
+ data.remaining_buffer(),
+ data.original_position(),
+ )?)
+ } else {
+ ElementItems::Functions(SectionLimited::new(
+ data.remaining_buffer(),
+ data.original_position(),
+ )?)
+ };
+
+ let elem_end = reader.original_position();
+ let range = elem_start..elem_end;
+
+ Ok(Element {
+ kind,
+ items,
+ ty,
+ range,
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/exports.rs b/third_party/rust/wasmparser/src/readers/core/exports.rs
new file mode 100644
index 0000000000..c1bd62626b
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/exports.rs
@@ -0,0 +1,65 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, FromReader, Result, SectionLimited};
+
+/// A reader for the export section of a WebAssembly module.
+pub type ExportSectionReader<'a> = SectionLimited<'a, Export<'a>>;
+
+/// External types as defined [here].
+///
+/// [here]: https://webassembly.github.io/spec/core/syntax/types.html#external-types
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum ExternalKind {
+ /// The external kind is a function.
+ Func,
+ /// The external kind if a table.
+ Table,
+ /// The external kind is a memory.
+ Memory,
+ /// The external kind is a global.
+ Global,
+ /// The external kind is a tag.
+ Tag,
+}
+
+/// Represents an export in a WebAssembly module.
+#[derive(Debug, Copy, Clone)]
+pub struct Export<'a> {
+ /// The name of the exported item.
+ pub name: &'a str,
+ /// The kind of the export.
+ pub kind: ExternalKind,
+ /// The index of the exported item.
+ pub index: u32,
+}
+
+impl<'a> FromReader<'a> for Export<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(Export {
+ name: reader.read_string()?,
+ kind: reader.read()?,
+ index: reader.read_var_u32()?,
+ })
+ }
+}
+
+impl<'a> FromReader<'a> for ExternalKind {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let offset = reader.original_position();
+ let byte = reader.read_u8()?;
+ BinaryReader::external_kind_from_byte(byte, offset)
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/functions.rs b/third_party/rust/wasmparser/src/readers/core/functions.rs
new file mode 100644
index 0000000000..ebddce05a3
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/functions.rs
@@ -0,0 +1,17 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/// A reader for the function section of a WebAssembly module.
+pub type FunctionSectionReader<'a> = crate::SectionLimited<'a, u32>;
diff --git a/third_party/rust/wasmparser/src/readers/core/globals.rs b/third_party/rust/wasmparser/src/readers/core/globals.rs
new file mode 100644
index 0000000000..6fd99bc0b8
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/globals.rs
@@ -0,0 +1,49 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, ConstExpr, FromReader, GlobalType, Result, SectionLimited};
+
+/// Represents a core WebAssembly global.
+#[derive(Debug, Copy, Clone)]
+pub struct Global<'a> {
+ /// The global's type.
+ pub ty: GlobalType,
+ /// The global's initialization expression.
+ pub init_expr: ConstExpr<'a>,
+}
+
+/// A reader for the global section of a WebAssembly module.
+pub type GlobalSectionReader<'a> = SectionLimited<'a, Global<'a>>;
+
+impl<'a> FromReader<'a> for Global<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let ty = reader.read()?;
+ let init_expr = reader.read()?;
+ Ok(Global { ty, init_expr })
+ }
+}
+
+impl<'a> FromReader<'a> for GlobalType {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(GlobalType {
+ content_type: reader.read()?,
+ mutable: match reader.read_u8()? {
+ 0x00 => false,
+ 0x01 => true,
+ _ => bail!(reader.original_position() - 1, "malformed mutability",),
+ },
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/imports.rs b/third_party/rust/wasmparser/src/readers/core/imports.rs
new file mode 100644
index 0000000000..d2a33c89e3
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/imports.rs
@@ -0,0 +1,76 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{
+ BinaryReader, ExternalKind, FromReader, GlobalType, MemoryType, Result, SectionLimited,
+ TableType, TagType,
+};
+
+/// Represents a reference to a type definition in a WebAssembly module.
+#[derive(Debug, Clone, Copy)]
+pub enum TypeRef {
+ /// The type is a function.
+ ///
+ /// The value is an index into the type section.
+ Func(u32),
+ /// The type is a table.
+ Table(TableType),
+ /// The type is a memory.
+ Memory(MemoryType),
+ /// The type is a global.
+ Global(GlobalType),
+ /// The type is a tag.
+ ///
+ /// This variant is only used for the exception handling proposal.
+ ///
+ /// The value is an index in the types index space.
+ Tag(TagType),
+}
+
+/// Represents an import in a WebAssembly module.
+#[derive(Debug, Copy, Clone)]
+pub struct Import<'a> {
+ /// The module being imported from.
+ pub module: &'a str,
+ /// The name of the imported item.
+ pub name: &'a str,
+ /// The type of the imported item.
+ pub ty: TypeRef,
+}
+
+/// A reader for the import section of a WebAssembly module.
+pub type ImportSectionReader<'a> = SectionLimited<'a, Import<'a>>;
+
+impl<'a> FromReader<'a> for Import<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(Import {
+ module: reader.read()?,
+ name: reader.read()?,
+ ty: reader.read()?,
+ })
+ }
+}
+
+impl<'a> FromReader<'a> for TypeRef {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read()? {
+ ExternalKind::Func => TypeRef::Func(reader.read_var_u32()?),
+ ExternalKind::Table => TypeRef::Table(reader.read()?),
+ ExternalKind::Memory => TypeRef::Memory(reader.read()?),
+ ExternalKind::Global => TypeRef::Global(reader.read()?),
+ ExternalKind::Tag => TypeRef::Tag(reader.read()?),
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/init.rs b/third_party/rust/wasmparser/src/readers/core/init.rs
new file mode 100644
index 0000000000..fcd3bd73c9
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/init.rs
@@ -0,0 +1,51 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, FromReader, OperatorsReader, Result};
+
+/// Represents an initialization expression.
+#[derive(Debug, Copy, Clone)]
+pub struct ConstExpr<'a> {
+ offset: usize,
+ data: &'a [u8],
+}
+
+impl<'a> ConstExpr<'a> {
+ /// Constructs a new `ConstExpr` from the given data and offset.
+ pub fn new(data: &[u8], offset: usize) -> ConstExpr {
+ ConstExpr { offset, data }
+ }
+
+ /// Gets a binary reader for the initialization expression.
+ pub fn get_binary_reader(&self) -> BinaryReader<'a> {
+ BinaryReader::new_with_offset(self.data, self.offset)
+ }
+
+ /// Gets an operators reader for the initialization expression.
+ pub fn get_operators_reader(&self) -> OperatorsReader<'a> {
+ OperatorsReader::new(self.get_binary_reader())
+ }
+}
+
+impl<'a> FromReader<'a> for ConstExpr<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ // FIXME(#188) ideally shouldn't need to skip here
+ let reader = reader.skip(|r| r.skip_const_expr())?;
+ Ok(ConstExpr::new(
+ reader.remaining_buffer(),
+ reader.original_position(),
+ ))
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/memories.rs b/third_party/rust/wasmparser/src/readers/core/memories.rs
new file mode 100644
index 0000000000..d1941b1cdc
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/memories.rs
@@ -0,0 +1,56 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, FromReader, MemoryType, Result, SectionLimited};
+
+/// A reader for the memory section of a WebAssembly module.
+pub type MemorySectionReader<'a> = SectionLimited<'a, MemoryType>;
+
+impl<'a> FromReader<'a> for MemoryType {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let pos = reader.original_position();
+ let flags = reader.read_u8()?;
+ if (flags & !0b111) != 0 {
+ bail!(pos, "invalid memory limits flags");
+ }
+
+ let memory64 = flags & 0b100 != 0;
+ let shared = flags & 0b010 != 0;
+ let has_max = flags & 0b001 != 0;
+ Ok(MemoryType {
+ memory64,
+ shared,
+ // FIXME(WebAssembly/memory64#21) as currently specified if the
+ // `shared` flag is set we should be reading a 32-bit limits field
+ // here. That seems a bit odd to me at the time of this writing so
+ // I've taken the liberty of reading a 64-bit limits field in those
+ // situations. I suspect that this is a typo in the spec, but if not
+ // we'll need to update this to read a 32-bit limits field when the
+ // shared flag is set.
+ initial: if memory64 {
+ reader.read_var_u64()?
+ } else {
+ reader.read_var_u32()?.into()
+ },
+ maximum: if !has_max {
+ None
+ } else if memory64 {
+ Some(reader.read_var_u64()?)
+ } else {
+ Some(reader.read_var_u32()?.into())
+ },
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/names.rs b/third_party/rust/wasmparser/src/readers/core/names.rs
new file mode 100644
index 0000000000..aa8a11dde2
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/names.rs
@@ -0,0 +1,153 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{
+ BinaryReader, BinaryReaderError, FromReader, Result, SectionLimited, Subsection, Subsections,
+};
+use std::ops::Range;
+
+/// Represents a name map from the names custom section.
+pub type NameMap<'a> = SectionLimited<'a, Naming<'a>>;
+
+/// Represents a name for an index from the names section.
+#[derive(Debug, Copy, Clone)]
+pub struct Naming<'a> {
+ /// The index being named.
+ pub index: u32,
+ /// The name for the index.
+ pub name: &'a str,
+}
+
+impl<'a> FromReader<'a> for Naming<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let index = reader.read_var_u32()?;
+ let name = reader.read_string()?;
+ Ok(Naming { index, name })
+ }
+}
+
+/// Represents a reader for indirect names from the names custom section.
+pub type IndirectNameMap<'a> = SectionLimited<'a, IndirectNaming<'a>>;
+
+/// Represents an indirect name in the names custom section.
+#[derive(Debug, Clone)]
+pub struct IndirectNaming<'a> {
+ /// The indirect index of the name.
+ pub index: u32,
+ /// The map of names within the `index` prior.
+ pub names: NameMap<'a>,
+}
+
+impl<'a> FromReader<'a> for IndirectNaming<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let index = reader.read_var_u32()?;
+
+ // Skip the `NameMap` manually here.
+ //
+ // FIXME(#188) shouldn't need to skip here
+ let names = reader.skip(|reader| {
+ let count = reader.read_var_u32()?;
+ for _ in 0..count {
+ reader.read_var_u32()?;
+ reader.skip_string()?;
+ }
+ Ok(())
+ })?;
+
+ Ok(IndirectNaming {
+ index,
+ names: NameMap::new(names.remaining_buffer(), names.original_position())?,
+ })
+ }
+}
+
+/// Represents a name read from the names custom section.
+#[derive(Clone)]
+pub enum Name<'a> {
+ /// The name is for the module.
+ Module {
+ /// The specified name.
+ name: &'a str,
+ /// The byte range that `name` occupies in the original binary.
+ name_range: Range<usize>,
+ },
+ /// The name is for the functions.
+ Function(NameMap<'a>),
+ /// The name is for the function locals.
+ Local(IndirectNameMap<'a>),
+ /// The name is for the function labels.
+ Label(IndirectNameMap<'a>),
+ /// The name is for the types.
+ Type(NameMap<'a>),
+ /// The name is for the tables.
+ Table(NameMap<'a>),
+ /// The name is for the memories.
+ Memory(NameMap<'a>),
+ /// The name is for the globals.
+ Global(NameMap<'a>),
+ /// The name is for the element segments.
+ Element(NameMap<'a>),
+ /// The name is for the data segments.
+ Data(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>,
+ },
+}
+
+/// A reader for the name custom section of a WebAssembly module.
+pub type NameSectionReader<'a> = Subsections<'a, Name<'a>>;
+
+impl<'a> Subsection<'a> for Name<'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(),
+ ));
+ }
+ Name::Module {
+ name,
+ name_range: offset..offset + reader.position,
+ }
+ }
+ 1 => Name::Function(NameMap::new(data, offset)?),
+ 2 => Name::Local(IndirectNameMap::new(data, offset)?),
+ 3 => Name::Label(IndirectNameMap::new(data, offset)?),
+ 4 => Name::Type(NameMap::new(data, offset)?),
+ 5 => Name::Table(NameMap::new(data, offset)?),
+ 6 => Name::Memory(NameMap::new(data, offset)?),
+ 7 => Name::Global(NameMap::new(data, offset)?),
+ 8 => Name::Element(NameMap::new(data, offset)?),
+ 9 => Name::Data(NameMap::new(data, offset)?),
+ ty => Name::Unknown {
+ ty,
+ data,
+ range: offset..offset + data.len(),
+ },
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/operators.rs b/third_party/rust/wasmparser/src/readers/core/operators.rs
new file mode 100644
index 0000000000..d1312c259f
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/operators.rs
@@ -0,0 +1,354 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, BinaryReaderError, Result, ValType};
+
+/// Represents a block type.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum BlockType {
+ /// The block produces consumes nor produces any values.
+ Empty,
+ /// The block produces a singular value of the given type ([] -> \[t]).
+ Type(ValType),
+ /// The block is described by a function type.
+ ///
+ /// The index is to a function type in the types section.
+ FuncType(u32),
+}
+
+/// Represents a memory immediate in a WebAssembly memory instruction.
+#[derive(Debug, Copy, Clone)]
+pub struct MemArg {
+ /// Alignment, stored as `n` where the actual alignment is `2^n`
+ pub align: u8,
+ /// Maximum alignment, stored as `n` where the actual alignment is `2^n`.
+ ///
+ /// Note that this field is not actually read from the binary format, it
+ /// will be a constant depending on which instruction this `MemArg` is a
+ /// payload for.
+ pub max_align: u8,
+ /// A fixed byte-offset that this memory immediate specifies.
+ ///
+ /// Note that the memory64 proposal can specify a full 64-bit byte offset
+ /// while otherwise only 32-bit offsets are allowed. Once validated
+ /// memory immediates for 32-bit memories are guaranteed to be at most
+ /// `u32::MAX` whereas 64-bit memories can use the full 64-bits.
+ pub offset: u64,
+ /// The index of the memory this immediate points to.
+ ///
+ /// Note that this points within the module's own memory index space, and
+ /// is always zero unless the multi-memory proposal of WebAssembly is
+ /// enabled.
+ pub memory: u32,
+}
+
+/// A br_table entries representation.
+#[derive(Clone)]
+pub struct BrTable<'a> {
+ pub(crate) reader: crate::BinaryReader<'a>,
+ pub(crate) cnt: u32,
+ pub(crate) default: u32,
+}
+
+/// An IEEE binary32 immediate floating point value, represented as a u32
+/// containing the bit pattern.
+///
+/// All bit patterns are allowed.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+pub struct Ieee32(pub(crate) u32);
+
+impl Ieee32 {
+ /// Gets the underlying bits of the 32-bit float.
+ pub fn bits(self) -> u32 {
+ self.0
+ }
+}
+
+/// An IEEE binary64 immediate floating point value, represented as a u64
+/// containing the bit pattern.
+///
+/// All bit patterns are allowed.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+pub struct Ieee64(pub(crate) u64);
+
+impl Ieee64 {
+ /// Gets the underlying bits of the 64-bit float.
+ pub fn bits(self) -> u64 {
+ self.0
+ }
+}
+
+/// Represents a 128-bit vector value.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+pub struct V128(pub(crate) [u8; 16]);
+
+impl V128 {
+ /// Gets the bytes of the vector value.
+ pub fn bytes(&self) -> &[u8; 16] {
+ &self.0
+ }
+
+ /// Gets a signed 128-bit integer value from the vector's bytes.
+ pub fn i128(&self) -> i128 {
+ i128::from_le_bytes(self.0)
+ }
+}
+
+macro_rules! define_operator {
+ ($(@$proposal:ident $op:ident $({ $($payload:tt)* })? => $visit:ident)*) => {
+ /// Instructions as defined [here].
+ ///
+ /// [here]: https://webassembly.github.io/spec/core/binary/instructions.html
+ #[derive(Debug, Clone)]
+ #[allow(missing_docs)]
+ pub enum Operator<'a> {
+ $(
+ $op $({ $($payload)* })?,
+ )*
+ }
+ }
+}
+for_each_operator!(define_operator);
+
+/// A reader for a core WebAssembly function's operators.
+#[derive(Clone)]
+pub struct OperatorsReader<'a> {
+ pub(crate) reader: BinaryReader<'a>,
+}
+
+impl<'a> OperatorsReader<'a> {
+ pub(crate) fn new(reader: BinaryReader<'a>) -> OperatorsReader<'a> {
+ OperatorsReader { reader }
+ }
+
+ /// Determines if the reader is at the end of the operators.
+ pub fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ /// Gets the original position of the reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Whether or not to allow 64-bit memory arguments in the
+ /// the operators being read.
+ ///
+ /// This is intended to be `true` when support for the memory64
+ /// WebAssembly proposal is also enabled.
+ pub fn allow_memarg64(&mut self, allow: bool) {
+ self.reader.allow_memarg64(allow);
+ }
+
+ /// Ensures the reader is at the end.
+ ///
+ /// This function returns an error if there is extra data after the operators.
+ pub fn ensure_end(&self) -> Result<()> {
+ if self.eof() {
+ return Ok(());
+ }
+ Err(BinaryReaderError::new(
+ "unexpected data at the end of operators",
+ self.reader.original_position(),
+ ))
+ }
+
+ /// Reads an operator from the reader.
+ pub fn read(&mut self) -> Result<Operator<'a>> {
+ self.reader.read_operator()
+ }
+
+ /// Converts to an iterator of operators paired with offsets.
+ pub fn into_iter_with_offsets(self) -> OperatorsIteratorWithOffsets<'a> {
+ OperatorsIteratorWithOffsets {
+ reader: self,
+ err: false,
+ }
+ }
+
+ /// Reads an operator with its offset.
+ pub fn read_with_offset(&mut self) -> Result<(Operator<'a>, usize)> {
+ let pos = self.reader.original_position();
+ Ok((self.read()?, pos))
+ }
+
+ /// Visit a single operator with the specified [`VisitOperator`] instance.
+ ///
+ /// See [`BinaryReader::visit_operator`] for more information.
+ pub fn visit_operator<T>(&mut self, visitor: &mut T) -> Result<<T as VisitOperator<'a>>::Output>
+ where
+ T: VisitOperator<'a>,
+ {
+ self.reader.visit_operator(visitor)
+ }
+
+ /// Gets a binary reader from this operators reader.
+ pub fn get_binary_reader(&self) -> BinaryReader<'a> {
+ self.reader.clone()
+ }
+}
+
+impl<'a> IntoIterator for OperatorsReader<'a> {
+ type Item = Result<Operator<'a>>;
+ type IntoIter = OperatorsIterator<'a>;
+
+ /// Reads content of the code section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::{Operator, CodeSectionReader, Result};
+ /// # let data: &[u8] = &[
+ /// # 0x01, 0x03, 0x00, 0x01, 0x0b];
+ /// let code_reader = CodeSectionReader::new(data, 0).unwrap();
+ /// for body in code_reader {
+ /// let body = body.expect("function body");
+ /// let mut op_reader = body.get_operators_reader().expect("op reader");
+ /// let ops = op_reader.into_iter().collect::<Result<Vec<Operator>>>().expect("ops");
+ /// assert!(
+ /// if let [Operator::Nop, Operator::End] = ops.as_slice() { true } else { false },
+ /// "found {:?}",
+ /// ops
+ /// );
+ /// }
+ /// ```
+ fn into_iter(self) -> Self::IntoIter {
+ OperatorsIterator {
+ reader: self,
+ err: false,
+ }
+ }
+}
+
+/// An iterator over a function's operators.
+pub struct OperatorsIterator<'a> {
+ reader: OperatorsReader<'a>,
+ err: bool,
+}
+
+impl<'a> Iterator for OperatorsIterator<'a> {
+ type Item = Result<Operator<'a>>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.err || self.reader.eof() {
+ return None;
+ }
+ let result = self.reader.read();
+ self.err = result.is_err();
+ Some(result)
+ }
+}
+
+/// An iterator over a function's operators with offsets.
+pub struct OperatorsIteratorWithOffsets<'a> {
+ reader: OperatorsReader<'a>,
+ err: bool,
+}
+
+impl<'a> Iterator for OperatorsIteratorWithOffsets<'a> {
+ type Item = Result<(Operator<'a>, usize)>;
+
+ /// Reads content of the code section with offsets.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::{Operator, CodeSectionReader, Result};
+ /// # let data: &[u8] = &[
+ /// # 0x01, 0x03, 0x00, /* offset = 23 */ 0x01, 0x0b];
+ /// let code_reader = CodeSectionReader::new(data, 20).unwrap();
+ /// for body in code_reader {
+ /// let body = body.expect("function body");
+ /// let mut op_reader = body.get_operators_reader().expect("op reader");
+ /// let ops = op_reader.into_iter_with_offsets().collect::<Result<Vec<(Operator, usize)>>>().expect("ops");
+ /// assert!(
+ /// if let [(Operator::Nop, 23), (Operator::End, 24)] = ops.as_slice() { true } else { false },
+ /// "found {:?}",
+ /// ops
+ /// );
+ /// }
+ /// ```
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.err || self.reader.eof() {
+ return None;
+ }
+ let result = self.reader.read_with_offset();
+ self.err = result.is_err();
+ Some(result)
+ }
+}
+
+macro_rules! define_visit_operator {
+ ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
+ $(
+ fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output;
+ )*
+ }
+}
+
+/// Trait implemented by types that can visit all [`Operator`] variants.
+#[allow(missing_docs)]
+pub trait VisitOperator<'a> {
+ /// The result type of the visitor.
+ type Output: 'a;
+
+ /// Visits the [`Operator`] `op` using the given `offset`.
+ ///
+ /// # Note
+ ///
+ /// This is a convenience method that is intended for non-performance
+ /// critical use cases. For performance critical implementations users
+ /// are recommended to directly use the respective `visit` methods or
+ /// implement [`VisitOperator`] on their own.
+ fn visit_operator(&mut self, op: &Operator<'a>) -> Self::Output {
+ macro_rules! visit_operator {
+ ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
+ match op {
+ $(
+ Operator::$op $({ $($arg),* })? => self.$visit($($($arg.clone()),*)?),
+ )*
+ }
+ }
+
+ }
+ for_each_operator!(visit_operator)
+ }
+
+ for_each_operator!(define_visit_operator);
+}
+
+macro_rules! define_visit_operator_delegate {
+ ($(@$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident)*) => {
+ $(
+ fn $visit(&mut self $($(,$arg: $argty)*)?) -> Self::Output {
+ V::$visit(&mut *self, $($($arg),*)?)
+ }
+ )*
+ }
+}
+
+impl<'a, 'b, V: VisitOperator<'a> + ?Sized> VisitOperator<'a> for &'b mut V {
+ type Output = V::Output;
+ fn visit_operator(&mut self, op: &Operator<'a>) -> Self::Output {
+ V::visit_operator(*self, op)
+ }
+ for_each_operator!(define_visit_operator_delegate);
+}
+
+impl<'a, V: VisitOperator<'a> + ?Sized> VisitOperator<'a> for Box<V> {
+ type Output = V::Output;
+ fn visit_operator(&mut self, op: &Operator<'a>) -> Self::Output {
+ V::visit_operator(&mut *self, op)
+ }
+ for_each_operator!(define_visit_operator_delegate);
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/producers.rs b/third_party/rust/wasmparser/src/readers/core/producers.rs
new file mode 100644
index 0000000000..07785ed75a
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/producers.rs
@@ -0,0 +1,78 @@
+/* Copyright 2019 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, FromReader, Result, SectionLimited};
+
+/// A reader for the producers custom section of a WebAssembly module.
+///
+/// # Examples
+///
+/// ```
+/// # let data: &[u8] = &[0x01, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65,
+/// # 0x02, 0x03, 0x77, 0x61, 0x74, 0x01, 0x31, 0x01, 0x43, 0x03, 0x39, 0x2e, 0x30];
+/// use wasmparser::{ProducersSectionReader, ProducersFieldValue, Result};
+/// let reader = ProducersSectionReader::new(data, 0).expect("producers reader");
+/// let field = reader.into_iter().next().unwrap().expect("producers field");
+/// assert!(field.name == "language");
+/// let value = field.values.into_iter().collect::<Result<Vec<_>>>().expect("values");
+/// assert!(value.len() == 2);
+/// assert!(value[0].name == "wat" && value[0].version == "1");
+/// assert!(value[1].name == "C" && value[1].version == "9.0");
+/// ```
+pub type ProducersSectionReader<'a> = SectionLimited<'a, ProducersField<'a>>;
+
+/// A field from the producers custom section.
+#[derive(Debug, Clone)]
+pub struct ProducersField<'a> {
+ /// The name of the field.
+ pub name: &'a str,
+ /// The values specified for this field
+ pub values: SectionLimited<'a, ProducersFieldValue<'a>>,
+}
+
+impl<'a> FromReader<'a> for ProducersField<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let name = reader.read_string()?;
+ let values = reader.skip(|reader| {
+ // FIXME(#188) ideally shouldn't need to skip here
+ for _ in 0..reader.read_var_u32()? {
+ reader.skip_string()?;
+ reader.skip_string()?;
+ }
+ Ok(())
+ })?;
+ Ok(ProducersField {
+ name,
+ values: SectionLimited::new(values.remaining_buffer(), values.original_position())?,
+ })
+ }
+}
+
+/// Represents a field value in the producers custom section.
+#[derive(Debug, Copy, Clone)]
+pub struct ProducersFieldValue<'a> {
+ /// The field name.
+ pub name: &'a str,
+ /// The field version.
+ pub version: &'a str,
+}
+
+impl<'a> FromReader<'a> for ProducersFieldValue<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let name = reader.read_string()?;
+ let version = reader.read_string()?;
+ Ok(ProducersFieldValue { name, version })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/tables.rs b/third_party/rust/wasmparser/src/readers/core/tables.rs
new file mode 100644
index 0000000000..211e415efd
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/tables.rs
@@ -0,0 +1,87 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, ConstExpr, FromReader, Result, SectionLimited, TableType};
+
+/// A reader for the table section of a WebAssembly module.
+pub type TableSectionReader<'a> = SectionLimited<'a, Table<'a>>;
+
+/// Type information about a table defined in the table section of a WebAssembly
+/// module.
+#[derive(Debug)]
+pub struct Table<'a> {
+ /// The type of this table, including its element type and its limits.
+ pub ty: TableType,
+ /// The initialization expression for the table.
+ pub init: TableInit<'a>,
+}
+
+/// Different modes of initializing a table.
+#[derive(Debug)]
+pub enum TableInit<'a> {
+ /// The table is initialized to all null elements.
+ RefNull,
+ /// Each element in the table is initialized with the specified constant
+ /// expression.
+ Expr(ConstExpr<'a>),
+}
+
+impl<'a> FromReader<'a> for Table<'a> {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let has_init_expr = if reader.peek()? == 0x40 {
+ reader.read_u8()?;
+ true
+ } else {
+ false
+ };
+
+ if has_init_expr {
+ if reader.read_u8()? != 0x00 {
+ bail!(reader.original_position() - 1, "invalid table encoding");
+ }
+ }
+
+ let ty = reader.read::<TableType>()?;
+ let init = if has_init_expr {
+ TableInit::Expr(reader.read()?)
+ } else {
+ TableInit::RefNull
+ };
+ Ok(Table { ty, init })
+ }
+}
+
+impl<'a> FromReader<'a> for TableType {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let element_type = reader.read()?;
+ let has_max = match reader.read_u8()? {
+ 0x00 => false,
+ 0x01 => true,
+ _ => {
+ bail!(
+ reader.original_position() - 1,
+ "invalid table resizable limits flags",
+ )
+ }
+ };
+ let initial = reader.read()?;
+ let maximum = if has_max { Some(reader.read()?) } else { None };
+ Ok(TableType {
+ element_type,
+ initial,
+ maximum,
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/tags.rs b/third_party/rust/wasmparser/src/readers/core/tags.rs
new file mode 100644
index 0000000000..746b3ea7ac
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/tags.rs
@@ -0,0 +1,32 @@
+/* Copyright 2020 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::{BinaryReader, FromReader, Result, SectionLimited, TagKind, TagType};
+
+/// A reader for the tags section of a WebAssembly module.
+pub type TagSectionReader<'a> = SectionLimited<'a, TagType>;
+
+impl<'a> FromReader<'a> for TagType {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let attribute = reader.read_u8()?;
+ if attribute != 0 {
+ bail!(reader.original_position() - 1, "invalid tag attributes");
+ }
+ Ok(TagType {
+ kind: TagKind::Exception,
+ func_type_idx: reader.read_var_u32()?,
+ })
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/types.rs b/third_party/rust/wasmparser/src/readers/core/types.rs
new file mode 100644
index 0000000000..4358e2670c
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/types.rs
@@ -0,0 +1,380 @@
+/* Copyright 2018 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use crate::limits::{MAX_WASM_FUNCTION_PARAMS, MAX_WASM_FUNCTION_RETURNS};
+use crate::{BinaryReader, FromReader, Result, SectionLimited};
+use std::fmt::Debug;
+
+/// Represents the types of values in a WebAssembly module.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum ValType {
+ /// The value type is i32.
+ I32,
+ /// The value type is i64.
+ I64,
+ /// The value type is f32.
+ F32,
+ /// The value type is f64.
+ F64,
+ /// The value type is v128.
+ V128,
+ /// The value type is a reference. Which type of reference is decided by
+ /// RefType. This is a change in syntax from the function references proposal,
+ /// which now provides FuncRef and ExternRef as sugar for the generic ref
+ /// construct.
+ Ref(RefType),
+}
+
+/// A reference type. When the function references feature is disabled, this
+/// only represents funcref and externref, using the following format:
+/// RefType { nullable: true, heap_type: Func | Extern })
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[repr(packed)]
+pub struct RefType {
+ /// Whether it's nullable
+ pub nullable: bool,
+ /// The relevant heap type
+ pub heap_type: HeapType,
+}
+
+impl RefType {
+ /// Alias for the wasm `funcref` type.
+ pub const FUNCREF: RefType = RefType {
+ nullable: true,
+ heap_type: HeapType::Func,
+ };
+ /// Alias for the wasm `externref` type.
+ pub const EXTERNREF: RefType = RefType {
+ nullable: true,
+ heap_type: HeapType::Extern,
+ };
+}
+
+impl From<RefType> for ValType {
+ fn from(ty: RefType) -> ValType {
+ ValType::Ref(ty)
+ }
+}
+
+/// Used as a performance optimization in HeapType. Call `.into()` to get the u32
+// A u16 forces 2-byte alignment, which forces HeapType to be 4 bytes,
+// which forces ValType to 5 bytes. This newtype is annotated as unaligned to
+// store the necessary bits compactly
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[repr(packed)]
+pub struct PackedIndex(u16);
+
+impl TryFrom<u32> for PackedIndex {
+ type Error = ();
+
+ fn try_from(idx: u32) -> Result<PackedIndex, ()> {
+ idx.try_into().map(PackedIndex).map_err(|_| ())
+ }
+}
+
+impl From<PackedIndex> for u32 {
+ fn from(x: PackedIndex) -> u32 {
+ x.0 as u32
+ }
+}
+
+/// A heap type from function references. When the proposal is disabled, Index
+/// is an invalid type.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum HeapType {
+ /// Function type index
+ /// Note: [PackedIndex] may need to be unpacked
+ TypedFunc(PackedIndex),
+ /// From reference types
+ Func,
+ /// From reference types
+ Extern,
+}
+
+impl ValType {
+ /// Alias for the wasm `funcref` type.
+ pub const FUNCREF: ValType = ValType::Ref(RefType::FUNCREF);
+ /// Alias for the wasm `externref` type.
+ pub const EXTERNREF: ValType = ValType::Ref(RefType::EXTERNREF);
+
+ /// Returns whether this value type is a "reference type".
+ ///
+ /// Only reference types are allowed in tables, for example, and with some
+ /// instructions. Current reference types include `funcref` and `externref`.
+ pub fn is_reference_type(&self) -> bool {
+ matches!(self, ValType::Ref(_))
+ }
+ /// Whether the type is defaultable according to function references
+ /// spec. This amounts to whether it's a non-nullable ref
+ pub fn is_defaultable(&self) -> bool {
+ !matches!(
+ self,
+ ValType::Ref(RefType {
+ nullable: false,
+ ..
+ })
+ )
+ }
+
+ pub(crate) fn is_valtype_byte(byte: u8) -> bool {
+ match byte {
+ 0x7F | 0x7E | 0x7D | 0x7C | 0x7B | 0x70 | 0x6F | 0x6B | 0x6C => true,
+ _ => false,
+ }
+ }
+}
+
+impl<'a> FromReader<'a> for ValType {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ match reader.peek()? {
+ 0x7F => {
+ reader.position += 1;
+ Ok(ValType::I32)
+ }
+ 0x7E => {
+ reader.position += 1;
+ Ok(ValType::I64)
+ }
+ 0x7D => {
+ reader.position += 1;
+ Ok(ValType::F32)
+ }
+ 0x7C => {
+ reader.position += 1;
+ Ok(ValType::F64)
+ }
+ 0x7B => {
+ reader.position += 1;
+ Ok(ValType::V128)
+ }
+ 0x70 | 0x6F | 0x6B | 0x6C => Ok(ValType::Ref(reader.read()?)),
+ _ => bail!(reader.original_position(), "invalid value type"),
+ }
+ }
+}
+
+impl<'a> FromReader<'a> for RefType {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ match reader.read()? {
+ 0x70 => Ok(RefType::FUNCREF),
+ 0x6F => Ok(RefType::EXTERNREF),
+ byte @ (0x6B | 0x6C) => Ok(RefType {
+ nullable: byte == 0x6C,
+ heap_type: reader.read()?,
+ }),
+ _ => bail!(reader.original_position(), "malformed reference type"),
+ }
+ }
+}
+
+impl<'a> FromReader<'a> for HeapType {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ match reader.peek()? {
+ 0x70 => {
+ reader.position += 1;
+ Ok(HeapType::Func)
+ }
+ 0x6F => {
+ reader.position += 1;
+ Ok(HeapType::Extern)
+ }
+ _ => {
+ let idx = match u32::try_from(reader.read_var_s33()?) {
+ Ok(idx) => idx,
+ Err(_) => {
+ bail!(reader.original_position(), "invalid function heap type",);
+ }
+ };
+ match idx.try_into() {
+ Ok(packed) => Ok(HeapType::TypedFunc(packed)),
+ Err(_) => {
+ bail!(reader.original_position(), "function index too large");
+ }
+ }
+ }
+ }
+ }
+}
+
+/// Represents a type in a WebAssembly module.
+#[derive(Debug, Clone)]
+pub enum Type {
+ /// The type is for a function.
+ Func(FuncType),
+}
+
+/// Represents a type of a function in a WebAssembly module.
+#[derive(Clone, Eq, PartialEq, Hash)]
+pub struct FuncType {
+ /// The combined parameters and result types.
+ params_results: Box<[ValType]>,
+ /// The number of parameter types.
+ len_params: usize,
+}
+
+impl Debug for FuncType {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("FuncType")
+ .field("params", &self.params())
+ .field("returns", &self.results())
+ .finish()
+ }
+}
+
+impl FuncType {
+ /// Creates a new [`FuncType`] from the given `params` and `results`.
+ pub fn new<P, R>(params: P, results: R) -> Self
+ where
+ P: IntoIterator<Item = ValType>,
+ R: IntoIterator<Item = ValType>,
+ {
+ let mut buffer = params.into_iter().collect::<Vec<_>>();
+ let len_params = buffer.len();
+ buffer.extend(results);
+ Self {
+ params_results: buffer.into(),
+ len_params,
+ }
+ }
+
+ /// Creates a new [`FuncType`] fom its raw parts.
+ ///
+ /// # Panics
+ ///
+ /// If `len_params` is greater than the length of `params_results` combined.
+ pub(crate) fn from_raw_parts(params_results: Box<[ValType]>, len_params: usize) -> Self {
+ assert!(len_params <= params_results.len());
+ Self {
+ params_results,
+ len_params,
+ }
+ }
+
+ /// Returns a shared slice to the parameter types of the [`FuncType`].
+ #[inline]
+ pub fn params(&self) -> &[ValType] {
+ &self.params_results[..self.len_params]
+ }
+
+ /// Returns a shared slice to the result types of the [`FuncType`].
+ #[inline]
+ pub fn results(&self) -> &[ValType] {
+ &self.params_results[self.len_params..]
+ }
+}
+
+/// Represents a table's type.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct TableType {
+ /// The table's element type.
+ pub element_type: RefType,
+ /// Initial size of this table, in elements.
+ pub initial: u32,
+ /// Optional maximum size of the table, in elements.
+ pub maximum: Option<u32>,
+}
+
+/// Represents a memory's type.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct MemoryType {
+ /// Whether or not this is a 64-bit memory, using i64 as an index. If this
+ /// is false it's a 32-bit memory using i32 as an index.
+ ///
+ /// This is part of the memory64 proposal in WebAssembly.
+ pub memory64: bool,
+
+ /// Whether or not this is a "shared" memory, indicating that it should be
+ /// send-able across threads and the `maximum` field is always present for
+ /// valid types.
+ ///
+ /// This is part of the threads proposal in WebAssembly.
+ pub shared: bool,
+
+ /// Initial size of this memory, in wasm pages.
+ ///
+ /// For 32-bit memories (when `memory64` is `false`) this is guaranteed to
+ /// be at most `u32::MAX` for valid types.
+ pub initial: u64,
+
+ /// Optional maximum size of this memory, in wasm pages.
+ ///
+ /// For 32-bit memories (when `memory64` is `false`) this is guaranteed to
+ /// be at most `u32::MAX` for valid types. This field is always present for
+ /// valid wasm memories when `shared` is `true`.
+ pub maximum: Option<u64>,
+}
+
+impl MemoryType {
+ /// Gets the index type for the memory.
+ pub fn index_type(&self) -> ValType {
+ if self.memory64 {
+ ValType::I64
+ } else {
+ ValType::I32
+ }
+ }
+}
+
+/// Represents a global's type.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct GlobalType {
+ /// The global's type.
+ pub content_type: ValType,
+ /// Whether or not the global is mutable.
+ pub mutable: bool,
+}
+
+/// Represents a tag kind.
+#[derive(Clone, Copy, Debug)]
+pub enum TagKind {
+ /// The tag is an exception type.
+ Exception,
+}
+
+/// A tag's type.
+#[derive(Clone, Copy, Debug)]
+pub struct TagType {
+ /// The kind of tag
+ pub kind: TagKind,
+ /// The function type this tag uses.
+ pub func_type_idx: u32,
+}
+
+/// A reader for the type section of a WebAssembly module.
+pub type TypeSectionReader<'a> = SectionLimited<'a, Type>;
+
+impl<'a> FromReader<'a> for Type {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ Ok(match reader.read_u8()? {
+ 0x60 => Type::Func(reader.read()?),
+ x => return reader.invalid_leading_byte(x, "type"),
+ })
+ }
+}
+
+impl<'a> FromReader<'a> for FuncType {
+ fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
+ let mut params_results = reader
+ .read_iter(MAX_WASM_FUNCTION_PARAMS, "function params")?
+ .collect::<Result<Vec<_>>>()?;
+ let len_params = params_results.len();
+ let results = reader.read_iter(MAX_WASM_FUNCTION_RETURNS, "function returns")?;
+ params_results.reserve(results.size_hint().0);
+ for result in results {
+ params_results.push(result?);
+ }
+ Ok(FuncType::from_raw_parts(params_results.into(), len_params))
+ }
+}