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.rs15
-rw-r--r--third_party/rust/wasmparser/src/readers/component/aliases.rs127
-rw-r--r--third_party/rust/wasmparser/src/readers/component/canonicals.rs124
-rw-r--r--third_party/rust/wasmparser/src/readers/component/exports.rs108
-rw-r--r--third_party/rust/wasmparser/src/readers/component/imports.rs125
-rw-r--r--third_party/rust/wasmparser/src/readers/component/instances.rs240
-rw-r--r--third_party/rust/wasmparser/src/readers/component/start.rs66
-rw-r--r--third_party/rust/wasmparser/src/readers/component/types.rs445
-rw-r--r--third_party/rust/wasmparser/src/readers/core.rs37
-rw-r--r--third_party/rust/wasmparser/src/readers/core/code.rs270
-rw-r--r--third_party/rust/wasmparser/src/readers/core/custom.rs63
-rw-r--r--third_party/rust/wasmparser/src/readers/core/data.rs189
-rw-r--r--third_party/rust/wasmparser/src/readers/core/elements.rs333
-rw-r--r--third_party/rust/wasmparser/src/readers/core/exports.rs123
-rw-r--r--third_party/rust/wasmparser/src/readers/core/functions.rs95
-rw-r--r--third_party/rust/wasmparser/src/readers/core/globals.rs110
-rw-r--r--third_party/rust/wasmparser/src/readers/core/imports.rs129
-rw-r--r--third_party/rust/wasmparser/src/readers/core/init.rs46
-rw-r--r--third_party/rust/wasmparser/src/readers/core/linking.rs88
-rw-r--r--third_party/rust/wasmparser/src/readers/core/memories.rs93
-rw-r--r--third_party/rust/wasmparser/src/readers/core/names.rs308
-rw-r--r--third_party/rust/wasmparser/src/readers/core/operators.rs342
-rw-r--r--third_party/rust/wasmparser/src/readers/core/producers.rs211
-rw-r--r--third_party/rust/wasmparser/src/readers/core/relocs.rs198
-rw-r--r--third_party/rust/wasmparser/src/readers/core/tables.rs93
-rw-r--r--third_party/rust/wasmparser/src/readers/core/tags.rs92
-rw-r--r--third_party/rust/wasmparser/src/readers/core/types.rs279
27 files changed, 4349 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..268b264cce
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component.rs
@@ -0,0 +1,15 @@
+mod aliases;
+mod canonicals;
+mod exports;
+mod imports;
+mod instances;
+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::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..2ef6e78338
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/aliases.rs
@@ -0,0 +1,127 @@
+use crate::{
+ BinaryReader, ComponentExternalKind, ExternalKind, Result, SectionIteratorLimited,
+ SectionReader, SectionWithLimitedItems,
+};
+use std::ops::Range;
+
+/// 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,
+ },
+}
+
+/// A reader for the alias section of a WebAssembly component.
+#[derive(Clone)]
+pub struct ComponentAliasSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ComponentAliasSectionReader<'a> {
+ /// Constructs a new `ComponentAliasSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the alias section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::ComponentAliasSectionReader;
+ /// let data: &[u8] = &[0x01, 0x01, 0x00, 0x00, 0x03, b'f', b'o', b'o'];
+ /// let mut reader = ComponentAliasSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let alias = reader.read().expect("alias");
+ /// println!("Alias: {:?}", alias);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<ComponentAlias<'a>> {
+ self.reader.read_component_alias()
+ }
+}
+
+impl<'a> SectionReader for ComponentAliasSectionReader<'a> {
+ type Item = ComponentAlias<'a>;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ComponentAliasSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ComponentAliasSectionReader<'a> {
+ type Item = Result<ComponentAlias<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..321e63fad0
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/canonicals.rs
@@ -0,0 +1,124 @@
+use crate::{BinaryReader, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems};
+use std::ops::Range;
+
+/// 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.
+#[derive(Clone)]
+pub struct ComponentCanonicalSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ComponentCanonicalSectionReader<'a> {
+ /// Constructs a new `ComponentFunctionSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads function type index from the function section.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use wasmparser::ComponentCanonicalSectionReader;
+ /// # let data: &[u8] = &[0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00];
+ /// let mut reader = ComponentCanonicalSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let func = reader.read().expect("func");
+ /// println!("Function: {:?}", func);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<CanonicalFunction> {
+ self.reader.read_canonical_func()
+ }
+}
+
+impl<'a> SectionReader for ComponentCanonicalSectionReader<'a> {
+ type Item = CanonicalFunction;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ComponentCanonicalSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ComponentCanonicalSectionReader<'a> {
+ type Item = Result<CanonicalFunction>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..dc08131c3a
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/exports.rs
@@ -0,0 +1,108 @@
+use crate::{BinaryReader, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems};
+use std::ops::Range;
+
+/// 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,
+}
+
+/// 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 kind of the export.
+ pub kind: ComponentExternalKind,
+ /// The index of the exported item.
+ pub index: u32,
+}
+
+/// A reader for the export section of a WebAssembly component.
+#[derive(Clone)]
+pub struct ComponentExportSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ComponentExportSectionReader<'a> {
+ /// Constructs a new `ComponentExportSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the export section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::ComponentExportSectionReader;
+ ///
+ /// # let data: &[u8] = &[0x01, 0x03, b'f', b'o', b'o', 0x01, 0x00];
+ /// let mut reader = ComponentExportSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let export = reader.read().expect("export");
+ /// println!("Export: {:?}", export);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<ComponentExport<'a>> {
+ self.reader.read_component_export()
+ }
+}
+
+impl<'a> SectionReader for ComponentExportSectionReader<'a> {
+ type Item = ComponentExport<'a>;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ComponentExportSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ComponentExportSectionReader<'a> {
+ type Item = Result<ComponentExport<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..0b7b4faf86
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/imports.rs
@@ -0,0 +1,125 @@
+use crate::{
+ BinaryReader, ComponentValType, Result, SectionIteratorLimited, SectionReader,
+ SectionWithLimitedItems,
+};
+use std::ops::Range;
+
+/// Represents the type bounds for imports and exports.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum TypeBounds {
+ /// The type is bounded by equality.
+ Eq,
+}
+
+/// 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),
+}
+
+/// 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 type reference for the import.
+ pub ty: ComponentTypeRef,
+}
+
+/// A reader for the import section of a WebAssembly component.
+#[derive(Clone)]
+pub struct ComponentImportSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ComponentImportSectionReader<'a> {
+ /// Constructs a new `ComponentImportSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the import section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::ComponentImportSectionReader;
+ /// let data: &[u8] = &[0x01, 0x01, 0x41, 0x01, 0x66, 0x00, 0x00];
+ /// let mut reader = ComponentImportSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let import = reader.read().expect("import");
+ /// println!("Import: {:?}", import);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<ComponentImport<'a>> {
+ self.reader.read_component_import()
+ }
+}
+
+impl<'a> SectionReader for ComponentImportSectionReader<'a> {
+ type Item = ComponentImport<'a>;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ComponentImportSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ComponentImportSectionReader<'a> {
+ type Item = Result<ComponentImport<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..79cacfbe94
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/instances.rs
@@ -0,0 +1,240 @@
+use crate::{
+ BinaryReader, ComponentExport, ComponentExternalKind, Export, Result, SectionIteratorLimited,
+ SectionReader, SectionWithLimitedItems,
+};
+use std::ops::Range;
+
+/// 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.
+#[derive(Clone)]
+pub struct InstanceSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> InstanceSectionReader<'a> {
+ /// Constructs a new `InstanceSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the instance section.
+ ///
+ /// # 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 _ in 0..reader.get_count() {
+ /// let instance = reader.read().expect("instance");
+ /// println!("Instance: {:?}", instance);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<Instance<'a>> {
+ self.reader.read_instance()
+ }
+}
+
+impl<'a> SectionReader for InstanceSectionReader<'a> {
+ type Item = Instance<'a>;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for InstanceSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for InstanceSectionReader<'a> {
+ type Item = Result<Instance<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ /// Implements iterator over the instance section.
+ ///
+ /// # 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"));
+ /// }
+ /// ```
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
+
+/// 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.
+#[derive(Clone)]
+pub struct ComponentInstanceSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ComponentInstanceSectionReader<'a> {
+ /// Constructs a new `ComponentInstanceSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the instance section.
+ ///
+ /// # 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 _ in 0..reader.get_count() {
+ /// let instance = reader.read().expect("instance");
+ /// println!("Instance: {:?}", instance);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<ComponentInstance<'a>> {
+ self.reader.read_component_instance()
+ }
+}
+
+impl<'a> SectionReader for ComponentInstanceSectionReader<'a> {
+ type Item = ComponentInstance<'a>;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ComponentInstanceSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ComponentInstanceSectionReader<'a> {
+ type Item = Result<ComponentInstance<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ /// Implements iterator over the instance section.
+ ///
+ /// # 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"));
+ /// }
+ /// ```
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..7bfd0c8af4
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/start.rs
@@ -0,0 +1,66 @@
+use crate::{BinaryReader, Result, SectionReader};
+use std::ops::Range;
+
+/// 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,
+}
+
+/// A reader for the start section of a WebAssembly component.
+#[derive(Clone)]
+pub struct ComponentStartSectionReader<'a>(BinaryReader<'a>);
+
+impl<'a> ComponentStartSectionReader<'a> {
+ /// Constructs a new `ComponentStartSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ Ok(Self(BinaryReader::new_with_offset(data, offset)))
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.0.original_position()
+ }
+
+ /// Reads the start function from the section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::ComponentStartSectionReader;
+ ///
+ /// # let data: &[u8] = &[0x00, 0x03, 0x01, 0x02, 0x03, 0x01];
+ /// let mut reader = ComponentStartSectionReader::new(data, 0).unwrap();
+ /// let start = reader.read().expect("start");
+ /// println!("Start: {:?}", start);
+ /// ```
+ pub fn read(&mut self) -> Result<ComponentStartFunction> {
+ self.0.read_component_start()
+ }
+}
+
+impl<'a> SectionReader for ComponentStartSectionReader<'a> {
+ type Item = ComponentStartFunction;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.0.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.0.range()
+ }
+}
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..bf891556ab
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/component/types.rs
@@ -0,0 +1,445 @@
+use crate::{
+ BinaryReader, ComponentAlias, ComponentImport, ComponentTypeRef, FuncType, Import, Result,
+ SectionIteratorLimited, SectionReader, SectionWithLimitedItems, Type, TypeRef,
+};
+use std::ops::Range;
+
+/// 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>]>),
+}
+
+/// 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>),
+}
+
+/// A reader for the core type section of a WebAssembly component.
+#[derive(Clone)]
+pub struct CoreTypeSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> CoreTypeSectionReader<'a> {
+ /// Constructs a new `CoreTypeSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets a count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the type section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::CoreTypeSectionReader;
+ /// let data: &[u8] = &[0x01, 0x60, 0x00, 0x00];
+ /// let mut reader = CoreTypeSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let ty = reader.read().expect("type");
+ /// println!("Type {:?}", ty);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<CoreType<'a>> {
+ self.reader.read_core_type()
+ }
+}
+
+impl<'a> SectionReader for CoreTypeSectionReader<'a> {
+ type Item = CoreType<'a>;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for CoreTypeSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for CoreTypeSectionReader<'a> {
+ type Item = Result<CoreType<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ /// Implements iterator over the type section.
+ ///
+ /// # 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"));
+ /// }
+ /// ```
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
+
+/// 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),
+}
+
+/// 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 {
+ 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 {
+ // Subtyping rules according to
+ // https://github.com/WebAssembly/component-model/blob/17f94ed1270a98218e0e796ca1dad1feb7e5c507/design/mvp/Subtyping.md
+ a == b
+ || matches!(
+ (a, b),
+ (Self::S8, Self::S16)
+ | (Self::S8, Self::S32)
+ | (Self::S8, Self::S64)
+ | (Self::U8, Self::U16)
+ | (Self::U8, Self::U32)
+ | (Self::U8, Self::U64)
+ | (Self::U8, Self::S16)
+ | (Self::U8, Self::S32)
+ | (Self::U8, Self::S64)
+ | (Self::S16, Self::S32)
+ | (Self::S16, Self::S64)
+ | (Self::U16, Self::U32)
+ | (Self::U16, Self::U64)
+ | (Self::U16, Self::S32)
+ | (Self::U16, Self::S64)
+ | (Self::S32, Self::S64)
+ | (Self::U32, Self::U64)
+ | (Self::U32, Self::S64)
+ | (Self::Float32, Self::Float64)
+ )
+ }
+}
+
+/// 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>]>),
+}
+
+/// 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 type reference for the export.
+ ty: ComponentTypeRef,
+ },
+ /// The component type declaration is for an import.
+ Import(ComponentImport<'a>),
+}
+
+/// 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 type reference for the export.
+ ty: ComponentTypeRef,
+ },
+}
+
+/// 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 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>,
+}
+
+/// 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>,
+ },
+}
+
+/// A reader for the type section of a WebAssembly component.
+#[derive(Clone)]
+pub struct ComponentTypeSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ComponentTypeSectionReader<'a> {
+ /// Constructs a new `ComponentTypeSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets a count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the type section.
+ ///
+ /// # 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 _ in 0..reader.get_count() {
+ /// let ty = reader.read().expect("type");
+ /// println!("Type {:?}", ty);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<ComponentType<'a>> {
+ self.reader.read_component_type()
+ }
+}
+
+impl<'a> SectionReader for ComponentTypeSectionReader<'a> {
+ type Item = ComponentType<'a>;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ComponentTypeSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ComponentTypeSectionReader<'a> {
+ type Item = Result<ComponentType<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ /// Implements iterator over the type section.
+ ///
+ /// # 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"));
+ /// }
+ /// ```
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..941f208548
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core.rs
@@ -0,0 +1,37 @@
+mod code;
+mod custom;
+mod data;
+mod elements;
+mod exports;
+mod functions;
+mod globals;
+mod imports;
+mod init;
+mod linking;
+mod memories;
+mod names;
+mod operators;
+mod producers;
+mod relocs;
+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::linking::*;
+pub use self::memories::*;
+pub use self::names::*;
+pub use self::operators::*;
+pub use self::producers::*;
+pub use self::relocs::*;
+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..500e3ad189
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/code.rs
@@ -0,0 +1,270 @@
+/* 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, OperatorsReader, Result, SectionIteratorLimited,
+ SectionReader, SectionWithLimitedItems, ValType,
+};
+use std::ops::Range;
+
+/// Represents a WebAssembly function body.
+#[derive(Debug, Clone, Copy)]
+pub struct FunctionBody<'a> {
+ offset: usize,
+ data: &'a [u8],
+ allow_memarg64: bool,
+}
+
+impl<'a> FunctionBody<'a> {
+ /// Constructs a new `FunctionBody` for the given data and offset.
+ pub fn new(offset: usize, data: &'a [u8]) -> Self {
+ Self {
+ offset,
+ data,
+ allow_memarg64: false,
+ }
+ }
+
+ /// 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.allow_memarg64 = allow;
+ }
+
+ /// Gets a binary reader for this function body.
+ pub fn get_binary_reader<'b>(&self) -> BinaryReader<'b>
+ where
+ 'a: 'b,
+ {
+ let mut reader = BinaryReader::new_with_offset(self.data, self.offset);
+ reader.allow_memarg64(self.allow_memarg64);
+ reader
+ }
+
+ fn skip_locals(reader: &mut BinaryReader) -> Result<()> {
+ let count = reader.read_var_u32()?;
+ for _ in 0..count {
+ reader.read_var_u32()?;
+ reader.read_var_u32()?;
+ }
+ Ok(())
+ }
+
+ /// Gets the locals reader for this function body.
+ pub fn get_locals_reader<'b>(&self) -> Result<LocalsReader<'b>>
+ where
+ 'a: 'b,
+ {
+ let mut reader = BinaryReader::new_with_offset(self.data, self.offset);
+ let count = reader.read_var_u32()?;
+ Ok(LocalsReader { reader, count })
+ }
+
+ /// Gets the operators reader for this function body.
+ pub fn get_operators_reader<'b>(&self) -> Result<OperatorsReader<'b>>
+ where
+ 'a: 'b,
+ {
+ let mut reader = BinaryReader::new_with_offset(self.data, self.offset);
+ Self::skip_locals(&mut reader)?;
+ let pos = reader.position;
+ let mut reader = OperatorsReader::new(&self.data[pos..], self.offset + pos);
+ reader.allow_memarg64(self.allow_memarg64);
+ Ok(reader)
+ }
+
+ /// Gets the range of the function body.
+ pub fn range(&self) -> Range<usize> {
+ self.offset..self.offset + self.data.len()
+ }
+}
+
+/// 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_var_u32()?;
+ let value_type = self.reader.read_val_type()?;
+ 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))
+ }
+}
+
+/// A reader for the code section of a WebAssembly module.
+pub struct CodeSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> CodeSectionReader<'a> {
+ /// Constructs a new `CodeSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<CodeSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(CodeSectionReader { reader, count })
+ }
+
+ /// Gets the original position of the reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ fn verify_body_end(&self, end: usize) -> Result<()> {
+ if self.reader.buffer.len() < end {
+ return Err(BinaryReaderError::new(
+ "function body extends past end of the code section",
+ self.reader.original_offset + self.reader.buffer.len(),
+ ));
+ }
+ Ok(())
+ }
+
+ /// Reads content of the code section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::CodeSectionReader;
+ /// # let data: &[u8] = &[
+ /// # 0x01, 0x03, 0x00, 0x01, 0x0b];
+ /// let mut code_reader = CodeSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..code_reader.get_count() {
+ /// let body = code_reader.read().expect("function body");
+ /// let mut binary_reader = body.get_binary_reader();
+ /// assert!(binary_reader.read_var_u32().expect("local count") == 0);
+ /// let op = binary_reader.read_operator().expect("first operator");
+ /// println!("First operator: {:?}", op);
+ /// }
+ /// ```
+ pub fn read<'b>(&mut self) -> Result<FunctionBody<'b>>
+ where
+ 'a: 'b,
+ {
+ let size = self.reader.read_var_u32()? as usize;
+ let body_start = self.reader.position;
+ let body_end = body_start + size;
+ self.verify_body_end(body_end)?;
+ self.reader.skip_to(body_end);
+ Ok(FunctionBody {
+ offset: self.reader.original_offset + body_start,
+ data: &self.reader.buffer[body_start..body_end],
+ allow_memarg64: false,
+ })
+ }
+}
+
+impl<'a> SectionReader for CodeSectionReader<'a> {
+ type Item = FunctionBody<'a>;
+ fn read(&mut self) -> Result<Self::Item> {
+ CodeSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ CodeSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for CodeSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ CodeSectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for CodeSectionReader<'a> {
+ type Item = Result<FunctionBody<'a>>;
+ type IntoIter = SectionIteratorLimited<CodeSectionReader<'a>>;
+
+ /// Implements iterator over the code section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::CodeSectionReader;
+ /// # let data: &[u8] = &[
+ /// # 0x01, 0x03, 0x00, 0x01, 0x0b];
+ /// let mut code_reader = CodeSectionReader::new(data, 0).unwrap();
+ /// for body in code_reader {
+ /// let mut binary_reader = body.expect("b").get_binary_reader();
+ /// assert!(binary_reader.read_var_u32().expect("local count") == 0);
+ /// let op = binary_reader.read_operator().expect("first operator");
+ /// println!("First operator: {:?}", op);
+ /// }
+ /// ```
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..8843f1aa50
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/data.rs
@@ -0,0 +1,189 @@
+/* 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, Result, SectionIteratorLimited, SectionReader,
+ SectionWithLimitedItems,
+};
+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.
+#[derive(Clone)]
+pub struct DataSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> DataSectionReader<'a> {
+ /// Constructs a new `DataSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<DataSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(DataSectionReader { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ fn verify_data_end(&self, end: usize) -> Result<()> {
+ if self.reader.buffer.len() < end {
+ return Err(BinaryReaderError::new(
+ "unexpected end of section or function: data segment extends past end of the data section",
+ self.reader.original_offset + self.reader.buffer.len(),
+ ));
+ }
+ Ok(())
+ }
+
+ /// Reads content of the data section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::{DataSectionReader, DataKind};
+ /// # let data: &[u8] = &[
+ /// # 0x01, 0x00, 0x41, 0x80, 0x08, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x00];
+ /// let mut data_reader = DataSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..data_reader.get_count() {
+ /// let data = data_reader.read().expect("data");
+ /// println!("Data: {:?}", data);
+ /// if let DataKind::Active { offset_expr, .. } = data.kind {
+ /// let mut offset_expr_reader = offset_expr.get_binary_reader();
+ /// let op = offset_expr_reader.read_operator().expect("op");
+ /// println!("offset expression: {:?}", op);
+ /// }
+ /// }
+ /// ```
+ pub fn read<'b>(&mut self) -> Result<Data<'b>>
+ where
+ 'a: 'b,
+ {
+ let segment_start = self.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 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 = self.reader.read_var_u32()?;
+ let kind = match flags {
+ 1 => DataKind::Passive,
+ 0 | 2 => {
+ let memory_index = if flags == 0 {
+ 0
+ } else {
+ self.reader.read_var_u32()?
+ };
+ let offset_expr = {
+ let expr_offset = self.reader.position;
+ self.reader.skip_const_expr()?;
+ let data = &self.reader.buffer[expr_offset..self.reader.position];
+ ConstExpr::new(data, self.reader.original_offset + expr_offset)
+ };
+ DataKind::Active {
+ memory_index,
+ offset_expr,
+ }
+ }
+ _ => {
+ return Err(BinaryReaderError::new(
+ "invalid flags byte in data segment",
+ self.reader.original_position() - 1,
+ ));
+ }
+ };
+
+ let data_len = self.reader.read_var_u32()? as usize;
+ let data_end = self.reader.position + data_len;
+ self.verify_data_end(data_end)?;
+ let data = &self.reader.buffer[self.reader.position..data_end];
+ self.reader.skip_to(data_end);
+
+ let segment_end = self.reader.original_position();
+ let range = segment_start..segment_end;
+
+ Ok(Data { kind, data, range })
+ }
+}
+
+impl<'a> SectionReader for DataSectionReader<'a> {
+ type Item = Data<'a>;
+ fn read(&mut self) -> Result<Self::Item> {
+ DataSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ DataSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for DataSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ DataSectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for DataSectionReader<'a> {
+ type Item = Result<Data<'a>>;
+ type IntoIter = SectionIteratorLimited<DataSectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..3eb0735d4f
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/elements.rs
@@ -0,0 +1,333 @@
+/* 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, Result, SectionIteratorLimited,
+ SectionReader, SectionWithLimitedItems, ValType,
+};
+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: ValType,
+ /// 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(Debug, Copy, Clone)]
+pub struct ElementItems<'a> {
+ exprs: bool,
+ offset: usize,
+ data: &'a [u8],
+}
+
+/// Represents an individual item of an element segment.
+#[derive(Debug)]
+pub enum ElementItem<'a> {
+ /// The item is a function index.
+ Func(u32),
+ /// The item is an initialization expression.
+ Expr(ConstExpr<'a>),
+}
+
+impl<'a> ElementItems<'a> {
+ /// Gets an items reader for the items in an element segment.
+ pub fn get_items_reader<'b>(&self) -> Result<ElementItemsReader<'b>>
+ where
+ 'a: 'b,
+ {
+ ElementItemsReader::new(self.data, self.offset, self.exprs)
+ }
+}
+
+/// A reader for element items in an element segment.
+pub struct ElementItemsReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+ exprs: bool,
+}
+
+impl<'a> ElementItemsReader<'a> {
+ /// Constructs a new `ElementItemsReader` for the given data and offset.
+ pub fn new(data: &[u8], offset: usize, exprs: bool) -> Result<ElementItemsReader> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(ElementItemsReader {
+ reader,
+ count,
+ exprs,
+ })
+ }
+
+ /// Gets the original position of the reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of element items in the segment.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Whether or not initialization expressions are used.
+ pub fn uses_exprs(&self) -> bool {
+ self.exprs
+ }
+
+ /// Reads an element item from the segment.
+ pub fn read(&mut self) -> Result<ElementItem<'a>> {
+ if self.exprs {
+ let expr = self.reader.read_const_expr()?;
+ Ok(ElementItem::Expr(expr))
+ } else {
+ let idx = self.reader.read_var_u32()?;
+ Ok(ElementItem::Func(idx))
+ }
+ }
+}
+
+impl<'a> IntoIterator for ElementItemsReader<'a> {
+ type Item = Result<ElementItem<'a>>;
+ type IntoIter = ElementItemsIterator<'a>;
+ fn into_iter(self) -> Self::IntoIter {
+ let count = self.count;
+ ElementItemsIterator {
+ reader: self,
+ left: count,
+ err: false,
+ }
+ }
+}
+
+/// An iterator over element items in an element segment.
+pub struct ElementItemsIterator<'a> {
+ reader: ElementItemsReader<'a>,
+ left: u32,
+ err: bool,
+}
+
+impl<'a> Iterator for ElementItemsIterator<'a> {
+ type Item = Result<ElementItem<'a>>;
+ 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))
+ }
+}
+
+/// A reader for the element section of a WebAssembly module.
+#[derive(Clone)]
+pub struct ElementSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ElementSectionReader<'a> {
+ /// Constructs a new `ElementSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<ElementSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(ElementSectionReader { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the element section.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// # let data: &[u8] = &[];
+ /// use wasmparser::{ElementSectionReader, ElementKind};
+ /// let mut element_reader = ElementSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..element_reader.get_count() {
+ /// let element = element_reader.read().expect("element");
+ /// if let ElementKind::Active { offset_expr, .. } = element.kind {
+ /// let mut offset_expr_reader = offset_expr.get_binary_reader();
+ /// let op = offset_expr_reader.read_operator().expect("op");
+ /// println!("offset expression: {:?}", op);
+ /// }
+ /// let mut items_reader = element.items.get_items_reader().expect("items reader");
+ /// for _ in 0..items_reader.get_count() {
+ /// let item = items_reader.read().expect("item");
+ /// println!(" Item: {:?}", item);
+ /// }
+ /// }
+ /// ```
+ pub fn read<'b>(&mut self) -> Result<Element<'b>>
+ where
+ 'a: 'b,
+ {
+ let elem_start = self.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 = self.reader.read_var_u32()?;
+ if (flags & !0b111) != 0 {
+ return Err(BinaryReaderError::new(
+ "invalid flags byte in element segment",
+ self.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 {
+ self.reader.read_var_u32()?
+ };
+ let offset_expr = {
+ let expr_offset = self.reader.position;
+ self.reader.skip_const_expr()?;
+ let data = &self.reader.buffer[expr_offset..self.reader.position];
+ ConstExpr::new(data, self.reader.original_offset + expr_offset)
+ };
+ ElementKind::Active {
+ table_index,
+ offset_expr,
+ }
+ };
+ let exprs = flags & 0b100 != 0;
+ let ty = if flags & 0b011 != 0 {
+ if exprs {
+ self.reader.read_val_type()?
+ } else {
+ match self.reader.read_external_kind()? {
+ ExternalKind::Func => ValType::FuncRef,
+ _ => {
+ return Err(BinaryReaderError::new(
+ "only the function external type is supported in elem segment",
+ self.reader.original_position() - 1,
+ ));
+ }
+ }
+ }
+ } else {
+ ValType::FuncRef
+ };
+ let data_start = self.reader.position;
+ let items_count = self.reader.read_var_u32()?;
+ if exprs {
+ for _ in 0..items_count {
+ self.reader.skip_const_expr()?;
+ }
+ } else {
+ for _ in 0..items_count {
+ self.reader.read_var_u32()?;
+ }
+ }
+ let data_end = self.reader.position;
+ let items = ElementItems {
+ offset: self.reader.original_offset + data_start,
+ data: &self.reader.buffer[data_start..data_end],
+ exprs,
+ };
+
+ let elem_end = self.reader.original_position();
+ let range = elem_start..elem_end;
+
+ Ok(Element {
+ kind,
+ items,
+ ty,
+ range,
+ })
+ }
+}
+
+impl<'a> SectionReader for ElementSectionReader<'a> {
+ type Item = Element<'a>;
+ fn read(&mut self) -> Result<Self::Item> {
+ ElementSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ ElementSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ElementSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ ElementSectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ElementSectionReader<'a> {
+ type Item = Result<Element<'a>>;
+ type IntoIter = SectionIteratorLimited<ElementSectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..0f4eb0a3a9
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/exports.rs
@@ -0,0 +1,123 @@
+/* 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, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems};
+use std::ops::Range;
+
+/// 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,
+}
+
+/// A reader for the export section of a WebAssembly module.
+#[derive(Clone)]
+pub struct ExportSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ExportSectionReader<'a> {
+ /// Constructs a new `ExportSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the export section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::ExportSectionReader;
+ ///
+ /// # let data: &[u8] = &[0x01, 0x01, 0x65, 0x00, 0x00];
+ /// let mut reader = ExportSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let export = reader.read().expect("export");
+ /// println!("Export: {:?}", export);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<Export<'a>> {
+ self.reader.read_export()
+ }
+}
+
+impl<'a> SectionReader for ExportSectionReader<'a> {
+ type Item = Export<'a>;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ExportSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ExportSectionReader<'a> {
+ type Item = Result<Export<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..a98b7fa9fe
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/functions.rs
@@ -0,0 +1,95 @@
+/* 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, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems};
+use std::ops::Range;
+
+/// A reader for the function section of a WebAssembly module.
+#[derive(Clone)]
+pub struct FunctionSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> FunctionSectionReader<'a> {
+ /// Constructs a new `FunctionSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads function type index from the function section.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use wasmparser::FunctionSectionReader;
+ /// # let data: &[u8] = &[0x01, 0x00];
+ /// let mut reader = FunctionSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let ty = reader.read().expect("function type index");
+ /// println!("Function type index: {}", ty);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<u32> {
+ self.reader.read_var_u32()
+ }
+}
+
+impl<'a> SectionReader for FunctionSectionReader<'a> {
+ type Item = u32;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for FunctionSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for FunctionSectionReader<'a> {
+ type Item = Result<u32>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..49e31c320a
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/globals.rs
@@ -0,0 +1,110 @@
+/* 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, GlobalType, Result, SectionIteratorLimited, SectionReader,
+ SectionWithLimitedItems,
+};
+use std::ops::Range;
+
+/// 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.
+#[derive(Clone)]
+pub struct GlobalSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> GlobalSectionReader<'a> {
+ /// Constructs a new `GlobalSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<GlobalSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(GlobalSectionReader { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the global section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::GlobalSectionReader;
+ /// # let data: &[u8] = &[0x01, 0x7F, 0x01, 0x41, 0x90, 0x88, 0x04, 0x0B];
+ /// let mut global_reader = GlobalSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..global_reader.get_count() {
+ /// let global = global_reader.read().expect("global");
+ /// println!("Global: {:?}", global);
+ /// let mut init_expr_reader = global.init_expr.get_binary_reader();
+ /// let op = init_expr_reader.read_operator().expect("op");
+ /// println!("Init const: {:?}", op);
+ /// }
+ /// ```
+ pub fn read<'b>(&mut self) -> Result<Global<'b>>
+ where
+ 'a: 'b,
+ {
+ let ty = self.reader.read_global_type()?;
+ let init_expr = self.reader.read_const_expr()?;
+ Ok(Global { ty, init_expr })
+ }
+}
+
+impl<'a> SectionReader for GlobalSectionReader<'a> {
+ type Item = Global<'a>;
+ fn read(&mut self) -> Result<Self::Item> {
+ GlobalSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ GlobalSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for GlobalSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ GlobalSectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for GlobalSectionReader<'a> {
+ type Item = Result<Global<'a>>;
+ type IntoIter = SectionIteratorLimited<GlobalSectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..a8a7a5d5ae
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/imports.rs
@@ -0,0 +1,129 @@
+/* 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, GlobalType, MemoryType, Result, SectionIteratorLimited, SectionReader,
+ SectionWithLimitedItems, TableType, TagType,
+};
+use std::ops::Range;
+
+/// 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.
+#[derive(Clone)]
+pub struct ImportSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ImportSectionReader<'a> {
+ /// Constructs a new `ImportSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the import section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::ImportSectionReader;
+ /// let data: &[u8] = &[0x01, 0x01, 0x41, 0x01, 0x66, 0x00, 0x00];
+ /// let mut reader = ImportSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let import = reader.read().expect("import");
+ /// println!("Import: {:?}", import);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<Import<'a>> {
+ self.reader.read_import()
+ }
+}
+
+impl<'a> SectionReader for ImportSectionReader<'a> {
+ type Item = Import<'a>;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ImportSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ImportSectionReader<'a> {
+ type Item = Result<Import<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..ad7e677add
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/init.rs
@@ -0,0 +1,46 @@
+/* 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, OperatorsReader};
+
+/// 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<'b>(&self) -> BinaryReader<'b>
+ where
+ 'a: 'b,
+ {
+ BinaryReader::new_with_offset(self.data, self.offset)
+ }
+
+ /// Gets an operators reader for the initialization expression.
+ pub fn get_operators_reader<'b>(&self) -> OperatorsReader<'b>
+ where
+ 'a: 'b,
+ {
+ OperatorsReader::new(self.data, self.offset)
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/linking.rs b/third_party/rust/wasmparser/src/readers/core/linking.rs
new file mode 100644
index 0000000000..a619288dd6
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/linking.rs
@@ -0,0 +1,88 @@
+/* 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, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems};
+use std::ops::Range;
+
+/// Represents a linking type.
+#[derive(Debug, Copy, Clone)]
+pub enum LinkingType {
+ /// The linking uses a stack pointer.
+ StackPointer(u32),
+}
+
+/// A reader for the linking custom section of a WebAssembly module.
+pub struct LinkingSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> LinkingSectionReader<'a> {
+ /// Constructs a new `LinkingSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<LinkingSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(LinkingSectionReader { reader, count })
+ }
+
+ /// Gets the count of items in the section.
+ 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 section.
+ pub fn read<'b>(&mut self) -> Result<LinkingType>
+ where
+ 'a: 'b,
+ {
+ self.reader.read_linking_type()
+ }
+}
+
+impl<'a> SectionReader for LinkingSectionReader<'a> {
+ type Item = LinkingType;
+ fn read(&mut self) -> Result<Self::Item> {
+ LinkingSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ LinkingSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for LinkingSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ LinkingSectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for LinkingSectionReader<'a> {
+ type Item = Result<LinkingType>;
+ type IntoIter = SectionIteratorLimited<LinkingSectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..23d1cdcac9
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/memories.rs
@@ -0,0 +1,93 @@
+/* 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, MemoryType, Result, SectionIteratorLimited, SectionReader,
+ SectionWithLimitedItems,
+};
+use std::ops::Range;
+
+/// A reader for the memory section of a WebAssembly module.
+#[derive(Clone)]
+pub struct MemorySectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> MemorySectionReader<'a> {
+ /// Constructs a new `MemorySectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<MemorySectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(MemorySectionReader { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the memory section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::MemorySectionReader;
+ /// # let data: &[u8] = &[0x01, 0x00, 0x02];
+ /// let mut memory_reader = MemorySectionReader::new(data, 0).unwrap();
+ /// for _ in 0..memory_reader.get_count() {
+ /// let memory = memory_reader.read().expect("memory");
+ /// println!("Memory: {:?}", memory);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<MemoryType> {
+ self.reader.read_memory_type()
+ }
+}
+
+impl<'a> SectionReader for MemorySectionReader<'a> {
+ type Item = MemoryType;
+ fn read(&mut self) -> Result<Self::Item> {
+ MemorySectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ MemorySectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for MemorySectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ MemorySectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for MemorySectionReader<'a> {
+ type Item = Result<MemoryType>;
+ type IntoIter = SectionIteratorLimited<MemorySectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..3780b8b193
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/names.rs
@@ -0,0 +1,308 @@
+/* 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, SectionIterator, SectionIteratorLimited,
+ SectionReader, SectionWithLimitedItems,
+};
+use std::ops::Range;
+
+/// 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,
+}
+
+/// Represents a name map from the names custom section.
+#[derive(Debug, Clone)]
+pub struct NameMap<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> NameMap<'a> {
+ /// Creates a new "name map" which parses the input data.
+ ///
+ /// This is intended to parse the `namemap` production in the name section
+ /// appending of the wasm spec.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<NameMap<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(NameMap { reader, count })
+ }
+}
+
+impl<'a> SectionReader for NameMap<'a> {
+ type Item = Naming<'a>;
+
+ fn read(&mut self) -> Result<Naming<'a>> {
+ let index = self.reader.read_var_u32()?;
+ let name = self.reader.read_string()?;
+ Ok(Naming { index, name })
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl SectionWithLimitedItems for NameMap<'_> {
+ fn get_count(&self) -> u32 {
+ self.count
+ }
+}
+
+impl<'a> IntoIterator for NameMap<'a> {
+ type Item = Result<Naming<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
+
+/// 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>,
+}
+
+/// Represents a reader for indirect names from the names custom section.
+#[derive(Clone)]
+pub struct IndirectNameMap<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> IndirectNameMap<'a> {
+ fn new(data: &'a [u8], offset: usize) -> Result<IndirectNameMap<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(IndirectNameMap { reader, count })
+ }
+}
+
+impl<'a> SectionReader for IndirectNameMap<'a> {
+ type Item = IndirectNaming<'a>;
+
+ fn read(&mut self) -> Result<IndirectNaming<'a>> {
+ let index = self.reader.read_var_u32()?;
+ let start = self.reader.position;
+
+ // Skip the `NameMap` manually here.
+ //
+ // FIXME(#188) shouldn't need to skip here
+ let count = self.reader.read_var_u32()?;
+ for _ in 0..count {
+ self.reader.read_var_u32()?;
+ self.reader.skip_string()?;
+ }
+
+ let end = self.reader.position;
+ Ok(IndirectNaming {
+ index: index,
+ names: NameMap::new(
+ &self.reader.buffer[start..end],
+ self.reader.original_offset + start,
+ )?,
+ })
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl SectionWithLimitedItems for IndirectNameMap<'_> {
+ fn get_count(&self) -> u32 {
+ self.count
+ }
+}
+
+impl<'a> IntoIterator for IndirectNameMap<'a> {
+ type Item = Result<IndirectNaming<'a>>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
+
+/// 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 struct NameSectionReader<'a> {
+ reader: BinaryReader<'a>,
+}
+
+impl<'a> NameSectionReader<'a> {
+ /// Constructs a new `NameSectionReader` from the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<NameSectionReader<'a>> {
+ Ok(NameSectionReader {
+ reader: BinaryReader::new_with_offset(data, offset),
+ })
+ }
+
+ fn verify_section_end(&self, end: usize) -> Result<()> {
+ if self.reader.buffer.len() < end {
+ return Err(BinaryReaderError::new(
+ "name entry extends past end of the code section",
+ self.reader.original_offset + self.reader.buffer.len(),
+ ));
+ }
+ Ok(())
+ }
+
+ /// Determines if the reader is at the end of the section.
+ pub fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Reads a name from the section.
+ pub fn read<'b>(&mut self) -> Result<Name<'b>>
+ where
+ 'a: 'b,
+ {
+ let subsection_id = self.reader.read_u7()?;
+ let payload_len = self.reader.read_var_u32()? as usize;
+ let payload_start = self.reader.position;
+ let payload_end = payload_start + payload_len;
+ self.verify_section_end(payload_end)?;
+ let offset = self.reader.original_offset + payload_start;
+ let data = &self.reader.buffer[payload_start..payload_end];
+ self.reader.skip_to(payload_end);
+
+ Ok(match subsection_id {
+ 0 => {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ 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 + payload_len,
+ },
+ })
+ }
+}
+
+impl<'a> SectionReader for NameSectionReader<'a> {
+ type Item = Name<'a>;
+ fn read(&mut self) -> Result<Self::Item> {
+ NameSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ NameSectionReader::eof(self)
+ }
+ fn original_position(&self) -> usize {
+ NameSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> IntoIterator for NameSectionReader<'a> {
+ type Item = Result<Name<'a>>;
+ type IntoIter = SectionIterator<NameSectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIterator::new(self)
+ }
+}
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..9d9dbd8c62
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/operators.rs
@@ -0,0 +1,342 @@
+/* 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<'b>(data: &'a [u8], offset: usize) -> OperatorsReader<'b>
+ where
+ 'a: 'b,
+ {
+ OperatorsReader {
+ reader: BinaryReader::new_with_offset(data, offset),
+ }
+ }
+
+ /// 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<'b>(&mut self) -> Result<Operator<'b>>
+ where
+ 'a: 'b,
+ {
+ self.reader.read_operator()
+ }
+
+ /// Converts to an iterator of operators paired with offsets.
+ pub fn into_iter_with_offsets<'b>(self) -> OperatorsIteratorWithOffsets<'b>
+ where
+ 'a: 'b,
+ {
+ OperatorsIteratorWithOffsets {
+ reader: self,
+ err: false,
+ }
+ }
+
+ /// Reads an operator with its offset.
+ pub fn read_with_offset<'b>(&mut self) -> Result<(Operator<'b>, usize)>
+ where
+ 'a: 'b,
+ {
+ 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 mut code_reader = CodeSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..code_reader.get_count() {
+ /// let body = code_reader.read().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 mut code_reader = CodeSectionReader::new(data, 20).unwrap();
+ /// for _ in 0..code_reader.get_count() {
+ /// let body = code_reader.read().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);
+}
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..4999aa45be
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/producers.rs
@@ -0,0 +1,211 @@
+/* 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, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems};
+use std::ops::Range;
+
+/// 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,
+}
+
+/// A reader for fields in the producers custom section.
+pub struct ProducersFieldValuesReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ProducersFieldValuesReader<'a> {
+ /// Gets the count of items in the reader.
+ 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()
+ }
+
+ fn skip(reader: &mut BinaryReader, values_count: u32) -> Result<()> {
+ for _ in 0..values_count {
+ reader.skip_string()?;
+ reader.skip_string()?;
+ }
+ Ok(())
+ }
+
+ /// Reads a field from the reader.
+ pub fn read<'b>(&mut self) -> Result<ProducersFieldValue<'b>>
+ where
+ 'a: 'b,
+ {
+ let name = self.reader.read_string()?;
+ let version = self.reader.read_string()?;
+ Ok(ProducersFieldValue { name, version })
+ }
+}
+
+impl<'a> IntoIterator for ProducersFieldValuesReader<'a> {
+ type Item = Result<ProducersFieldValue<'a>>;
+ type IntoIter = ProducersFieldValuesIterator<'a>;
+ fn into_iter(self) -> Self::IntoIter {
+ let count = self.count;
+ ProducersFieldValuesIterator {
+ reader: self,
+ left: count,
+ err: false,
+ }
+ }
+}
+
+/// An iterator over fields in the producers custom section.
+pub struct ProducersFieldValuesIterator<'a> {
+ reader: ProducersFieldValuesReader<'a>,
+ left: u32,
+ err: bool,
+}
+
+impl<'a> Iterator for ProducersFieldValuesIterator<'a> {
+ type Item = Result<ProducersFieldValue<'a>>;
+ 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))
+ }
+}
+
+/// A field from the producers custom section.
+#[derive(Debug, Copy, Clone)]
+pub struct ProducersField<'a> {
+ /// The name of the field.
+ pub name: &'a str,
+ values_count: u32,
+ values_data: &'a [u8],
+ values_offset: usize,
+}
+
+impl<'a> ProducersField<'a> {
+ /// Gets a reader of values for the field.
+ pub fn get_producer_field_values_reader<'b>(&self) -> Result<ProducersFieldValuesReader<'b>>
+ where
+ 'a: 'b,
+ {
+ Ok(ProducersFieldValuesReader {
+ reader: BinaryReader::new_with_offset(self.values_data, self.values_offset),
+ count: self.values_count,
+ })
+ }
+}
+
+/// A reader for the producers custom section of a WebAssembly module.
+pub struct ProducersSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> ProducersSectionReader<'a> {
+ /// Creates reader for the producers section.
+ ///
+ /// # 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 mut reader = ProducersSectionReader::new(data, 0).expect("producers reader");
+ /// let field = reader.read().expect("producers field");
+ /// assert!(field.name == "language");
+ /// let mut values_reader = field.get_producer_field_values_reader().expect("values reader");
+ /// let value = values_reader.into_iter().collect::<Result<Vec<ProducersFieldValue>>>().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 fn new(data: &'a [u8], offset: usize) -> Result<ProducersSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(ProducersSectionReader { reader, count })
+ }
+
+ /// Gets the original position of the reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the reader.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads an item from the reader.
+ pub fn read<'b>(&mut self) -> Result<ProducersField<'b>>
+ where
+ 'a: 'b,
+ {
+ let name = self.reader.read_string()?;
+ let values_count = self.reader.read_var_u32()?;
+ let values_start = self.reader.position;
+ ProducersFieldValuesReader::skip(&mut self.reader, values_count)?;
+ let values_end = self.reader.position;
+ Ok(ProducersField {
+ name,
+ values_count,
+ values_data: &self.reader.buffer[values_start..values_end],
+ values_offset: self.reader.original_offset + values_start,
+ })
+ }
+}
+
+impl<'a> SectionReader for ProducersSectionReader<'a> {
+ type Item = ProducersField<'a>;
+ fn read(&mut self) -> Result<Self::Item> {
+ ProducersSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ ProducersSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for ProducersSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ ProducersSectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for ProducersSectionReader<'a> {
+ type Item = Result<ProducersField<'a>>;
+ type IntoIter = SectionIteratorLimited<ProducersSectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
diff --git a/third_party/rust/wasmparser/src/readers/core/relocs.rs b/third_party/rust/wasmparser/src/readers/core/relocs.rs
new file mode 100644
index 0000000000..29a9e33faf
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/relocs.rs
@@ -0,0 +1,198 @@
+/* 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, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems};
+use std::ops::Range;
+
+/// Represents a relocation type.
+#[derive(Debug, Copy, Clone)]
+#[allow(missing_docs)]
+pub enum RelocType {
+ FunctionIndexLEB,
+ TableIndexSLEB,
+ TableIndexI32,
+ GlobalAddrLEB,
+ GlobalAddrSLEB,
+ GlobalAddrI32,
+ TypeIndexLEB,
+ GlobalIndexLEB,
+}
+
+/// Represents known custom section kinds.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub enum CustomSectionKind {
+ /// The custom section is not known.
+ Unknown,
+ /// The name custom section.
+ Name,
+ /// The producers custom section.
+ Producers,
+ /// The source mapping URL custom section.
+ SourceMappingURL,
+ /// The reloc custom section.
+ Reloc,
+ /// The linking custom section.
+ Linking,
+}
+
+/// Section code as defined [here].
+///
+/// [here]: https://webassembly.github.io/spec/core/binary/modules.html#sections
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub enum SectionCode<'a> {
+ /// The custom section.
+ Custom {
+ /// The name of the custom section.
+ name: &'a str,
+ /// The kind of the custom section.
+ kind: CustomSectionKind,
+ },
+ /// The type section.
+ Type,
+ /// The import section.
+ Import,
+ /// The function section.
+ Function,
+ /// The table section.
+ Table,
+ /// The memory section.
+ Memory,
+ /// The global section.
+ Global,
+ /// The export section.
+ Export,
+ /// The start section.
+ Start,
+ /// The element section.
+ Element,
+ /// The code section.
+ Code,
+ /// The data section.
+ Data,
+ /// The passive data count section.
+ DataCount,
+ /// The tag section.
+ Tag,
+}
+
+/// Represents a relocation entry.
+#[derive(Debug, Copy, Clone)]
+pub struct Reloc {
+ /// The relocation type.
+ pub ty: RelocType,
+ /// The relocation offset.
+ pub offset: u32,
+ /// The relocation index.
+ pub index: u32,
+ /// The relocation addend.
+ pub addend: Option<u32>,
+}
+
+/// A reader for the relocations custom section of a WebAssembly module.
+pub struct RelocSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ section_code: SectionCode<'a>,
+ count: u32,
+}
+
+impl<'a> RelocSectionReader<'a> {
+ /// Constructs a new `RelocSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<RelocSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+
+ let section_id_position = reader.position;
+ let section_id = reader.read_u7()?;
+ let section_code = reader.read_section_code(section_id, section_id_position)?;
+
+ let count = reader.read_var_u32()?;
+ Ok(RelocSectionReader {
+ reader,
+ section_code,
+ count,
+ })
+ }
+
+ /// Gets a count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Gets the section code from the section.
+ pub fn get_section_code<'b>(&self) -> SectionCode<'b>
+ where
+ 'a: 'b,
+ {
+ self.section_code
+ }
+
+ /// 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<Reloc> {
+ let ty = self.reader.read_reloc_type()?;
+ let offset = self.reader.read_var_u32()?;
+ let index = self.reader.read_var_u32()?;
+ let addend = match ty {
+ RelocType::FunctionIndexLEB
+ | RelocType::TableIndexSLEB
+ | RelocType::TableIndexI32
+ | RelocType::TypeIndexLEB
+ | RelocType::GlobalIndexLEB => None,
+ RelocType::GlobalAddrLEB | RelocType::GlobalAddrSLEB | RelocType::GlobalAddrI32 => {
+ Some(self.reader.read_var_u32()?)
+ }
+ };
+ Ok(Reloc {
+ ty,
+ offset,
+ index,
+ addend,
+ })
+ }
+}
+
+impl<'a> SectionReader for RelocSectionReader<'a> {
+ type Item = Reloc;
+ fn read(&mut self) -> Result<Self::Item> {
+ RelocSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ RelocSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for RelocSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ RelocSectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for RelocSectionReader<'a> {
+ type Item = Result<Reloc>;
+ type IntoIter = SectionIteratorLimited<RelocSectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..3121b5fe98
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/tables.rs
@@ -0,0 +1,93 @@
+/* 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, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems, TableType,
+};
+use std::ops::Range;
+
+/// A reader for the table section of a WebAssembly module.
+#[derive(Clone)]
+pub struct TableSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> TableSectionReader<'a> {
+ /// Constructs a new `TableSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<TableSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(TableSectionReader { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the table section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::TableSectionReader;
+ ///
+ /// # let data: &[u8] = &[0x01, 0x70, 0x01, 0x01, 0x01];
+ /// let mut table_reader = TableSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..table_reader.get_count() {
+ /// let table = table_reader.read().expect("table");
+ /// println!("Table: {:?}", table);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<TableType> {
+ self.reader.read_table_type()
+ }
+}
+
+impl<'a> SectionReader for TableSectionReader<'a> {
+ type Item = TableType;
+ fn read(&mut self) -> Result<Self::Item> {
+ TableSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ TableSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for TableSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ TableSectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for TableSectionReader<'a> {
+ type Item = Result<TableType>;
+ type IntoIter = SectionIteratorLimited<TableSectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..fd40779791
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/tags.rs
@@ -0,0 +1,92 @@
+/* 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, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems, TagType,
+};
+use std::ops::Range;
+
+/// A reader for the tags section of a WebAssembly module.
+#[derive(Clone)]
+pub struct TagSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> TagSectionReader<'a> {
+ /// Constructs a new `TagSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<TagSectionReader<'a>> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(TagSectionReader { reader, count })
+ }
+
+ /// Gets the original position of the section reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets the count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the tag section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::TagSectionReader;
+ /// # let data: &[u8] = &[0x01, 0x00, 0x01];
+ /// let mut reader = TagSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let ty = reader.read().expect("tag type");
+ /// println!("Tag type: {:?}", ty);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<TagType> {
+ self.reader.read_tag_type()
+ }
+}
+
+impl<'a> SectionReader for TagSectionReader<'a> {
+ type Item = TagType;
+ fn read(&mut self) -> Result<Self::Item> {
+ TagSectionReader::read(self)
+ }
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+ fn original_position(&self) -> usize {
+ TagSectionReader::original_position(self)
+ }
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for TagSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ TagSectionReader::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for TagSectionReader<'a> {
+ type Item = Result<TagType>;
+ type IntoIter = SectionIteratorLimited<TagSectionReader<'a>>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}
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..cb6d2e80af
--- /dev/null
+++ b/third_party/rust/wasmparser/src/readers/core/types.rs
@@ -0,0 +1,279 @@
+/* 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, Result, SectionIteratorLimited, SectionReader, SectionWithLimitedItems};
+use std::fmt::Debug;
+use std::ops::Range;
+
+/// 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 function reference.
+ FuncRef,
+ /// The value type is an extern reference.
+ ExternRef,
+}
+
+impl ValType {
+ /// 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::FuncRef | ValType::ExternRef)
+ }
+}
+
+/// 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: ValType,
+ /// 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.
+#[derive(Clone)]
+pub struct TypeSectionReader<'a> {
+ reader: BinaryReader<'a>,
+ count: u32,
+}
+
+impl<'a> TypeSectionReader<'a> {
+ /// Constructs a new `TypeSectionReader` for the given data and offset.
+ pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
+ let mut reader = BinaryReader::new_with_offset(data, offset);
+ let count = reader.read_var_u32()?;
+ Ok(Self { reader, count })
+ }
+
+ /// Gets the original position of the reader.
+ pub fn original_position(&self) -> usize {
+ self.reader.original_position()
+ }
+
+ /// Gets a count of items in the section.
+ pub fn get_count(&self) -> u32 {
+ self.count
+ }
+
+ /// Reads content of the type section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::TypeSectionReader;
+ /// let data: &[u8] = &[0x01, 0x60, 0x00, 0x00];
+ /// let mut reader = TypeSectionReader::new(data, 0).unwrap();
+ /// for _ in 0..reader.get_count() {
+ /// let ty = reader.read().expect("type");
+ /// println!("Type {:?}", ty);
+ /// }
+ /// ```
+ pub fn read(&mut self) -> Result<Type> {
+ self.reader.read_type()
+ }
+}
+
+impl<'a> SectionReader for TypeSectionReader<'a> {
+ type Item = Type;
+
+ fn read(&mut self) -> Result<Self::Item> {
+ Self::read(self)
+ }
+
+ fn eof(&self) -> bool {
+ self.reader.eof()
+ }
+
+ fn original_position(&self) -> usize {
+ Self::original_position(self)
+ }
+
+ fn range(&self) -> Range<usize> {
+ self.reader.range()
+ }
+}
+
+impl<'a> SectionWithLimitedItems for TypeSectionReader<'a> {
+ fn get_count(&self) -> u32 {
+ Self::get_count(self)
+ }
+}
+
+impl<'a> IntoIterator for TypeSectionReader<'a> {
+ type Item = Result<Type>;
+ type IntoIter = SectionIteratorLimited<Self>;
+
+ /// Implements iterator over the type section.
+ ///
+ /// # Examples
+ /// ```
+ /// use wasmparser::TypeSectionReader;
+ /// # let data: &[u8] = &[0x01, 0x60, 0x00, 0x00];
+ /// let mut reader = TypeSectionReader::new(data, 0).unwrap();
+ /// for ty in reader {
+ /// println!("Type {:?}", ty.expect("type"));
+ /// }
+ /// ```
+ fn into_iter(self) -> Self::IntoIter {
+ SectionIteratorLimited::new(self)
+ }
+}