//! Conversions from `wasmparser` to `wasm-encoder` to [`Reencode`] parsed wasm. //! //! The [`RoundtripReencoder`] allows encoding identical wasm to the parsed //! input. use crate::CoreTypeEncoder; use std::convert::Infallible; #[cfg(feature = "component-model")] mod component; #[cfg(feature = "component-model")] pub use self::component::*; #[allow(missing_docs)] // FIXME pub trait Reencode { type Error; fn data_index(&mut self, data: u32) -> u32 { utils::data_index(self, data) } fn element_index(&mut self, element: u32) -> u32 { utils::element_index(self, element) } fn function_index(&mut self, func: u32) -> u32 { utils::function_index(self, func) } fn global_index(&mut self, global: u32) -> u32 { utils::global_index(self, global) } fn memory_index(&mut self, memory: u32) -> u32 { utils::memory_index(self, memory) } fn table_index(&mut self, table: u32) -> u32 { utils::table_index(self, table) } fn tag_index(&mut self, tag: u32) -> u32 { utils::tag_index(self, tag) } fn type_index(&mut self, ty: u32) -> u32 { utils::type_index(self, ty) } fn type_index_unpacked( &mut self, ty: wasmparser::UnpackedIndex, ) -> Result> { utils::type_index_unpacked(self, ty) } fn external_index(&mut self, kind: wasmparser::ExternalKind, index: u32) -> u32 { match kind { wasmparser::ExternalKind::Func => self.function_index(index), wasmparser::ExternalKind::Table => self.table_index(index), wasmparser::ExternalKind::Memory => self.memory_index(index), wasmparser::ExternalKind::Global => self.global_index(index), wasmparser::ExternalKind::Tag => self.tag_index(index), } } fn abstract_heap_type( &mut self, value: wasmparser::AbstractHeapType, ) -> crate::AbstractHeapType { utils::abstract_heap_type(self, value) } fn array_type( &mut self, array_ty: wasmparser::ArrayType, ) -> Result> { utils::array_type(self, array_ty) } fn block_type( &mut self, arg: wasmparser::BlockType, ) -> Result> { utils::block_type(self, arg) } fn const_expr( &mut self, const_expr: wasmparser::ConstExpr, ) -> Result> { utils::const_expr(self, const_expr) } fn catch(&mut self, arg: wasmparser::Catch) -> crate::Catch { utils::catch(self, arg) } fn composite_type( &mut self, composite_ty: wasmparser::CompositeType, ) -> Result> { utils::composite_type(self, composite_ty) } fn entity_type( &mut self, type_ref: wasmparser::TypeRef, ) -> Result> { utils::entity_type(self, type_ref) } fn export_kind(&mut self, external_kind: wasmparser::ExternalKind) -> crate::ExportKind { utils::export_kind(self, external_kind) } fn field_type( &mut self, field_ty: wasmparser::FieldType, ) -> Result> { utils::field_type(self, field_ty) } fn func_type( &mut self, func_ty: wasmparser::FuncType, ) -> Result> { utils::func_type(self, func_ty) } fn cont_type( &mut self, cont_ty: wasmparser::ContType, ) -> Result> { utils::cont_type(self, cont_ty) } fn global_type( &mut self, global_ty: wasmparser::GlobalType, ) -> Result> { utils::global_type(self, global_ty) } fn handle(&mut self, on: wasmparser::Handle) -> crate::Handle { utils::handle(self, on) } fn heap_type( &mut self, heap_type: wasmparser::HeapType, ) -> Result> { utils::heap_type(self, heap_type) } fn instruction<'a>( &mut self, arg: wasmparser::Operator<'a>, ) -> Result, Error> { utils::instruction(self, arg) } fn memory_type(&mut self, memory_ty: wasmparser::MemoryType) -> crate::MemoryType { utils::memory_type(self, memory_ty) } fn mem_arg(&mut self, arg: wasmparser::MemArg) -> crate::MemArg { utils::mem_arg(self, arg) } fn ordering(&mut self, arg: wasmparser::Ordering) -> crate::Ordering { utils::ordering(self, arg) } fn ref_type( &mut self, ref_type: wasmparser::RefType, ) -> Result> { utils::ref_type(self, ref_type) } fn storage_type( &mut self, storage_ty: wasmparser::StorageType, ) -> Result> { utils::storage_type(self, storage_ty) } fn struct_type( &mut self, struct_ty: wasmparser::StructType, ) -> Result> { utils::struct_type(self, struct_ty) } fn sub_type( &mut self, sub_ty: wasmparser::SubType, ) -> Result> { utils::sub_type(self, sub_ty) } fn table_type( &mut self, table_ty: wasmparser::TableType, ) -> Result> { utils::table_type(self, table_ty) } fn tag_kind(&mut self, kind: wasmparser::TagKind) -> crate::TagKind { utils::tag_kind(self, kind) } fn tag_type(&mut self, tag_ty: wasmparser::TagType) -> crate::TagType { utils::tag_type(self, tag_ty) } fn val_type( &mut self, val_ty: wasmparser::ValType, ) -> Result> { utils::val_type(self, val_ty) } /// Parses the input `section` given from the `wasmparser` crate and /// adds the custom section to the `module`. fn parse_custom_section( &mut self, module: &mut crate::Module, section: wasmparser::CustomSectionReader<'_>, ) -> Result<(), Error> { utils::parse_custom_section(self, module, section) } /// Converts the input `section` given from the `wasmparser` crate into an /// encoded custom section. fn custom_section<'a>( &mut self, section: wasmparser::CustomSectionReader<'a>, ) -> crate::CustomSection<'a> { utils::custom_section(self, section) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the code to the `code` section. fn parse_code_section( &mut self, code: &mut crate::CodeSection, section: wasmparser::CodeSectionReader<'_>, ) -> Result<(), Error> { utils::parse_code_section(self, code, section) } /// Parses a single [`wasmparser::FunctionBody`] and adds it to the `code` section. fn parse_function_body( &mut self, code: &mut crate::CodeSection, func: wasmparser::FunctionBody<'_>, ) -> Result<(), Error> { utils::parse_function_body(self, code, func) } /// Create a new [`crate::Function`] by parsing the locals declarations from the /// provided [`wasmparser::FunctionBody`]. fn new_function_with_parsed_locals( &mut self, func: &wasmparser::FunctionBody<'_>, ) -> Result> { utils::new_function_with_parsed_locals(self, func) } /// Parses a single instruction from `reader` and adds it to `function`. fn parse_instruction<'a>( &mut self, reader: &mut wasmparser::OperatorsReader<'a>, ) -> Result, Error> { utils::parse_instruction(self, reader) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the data to the `data` section. fn parse_data_section( &mut self, data: &mut crate::DataSection, section: wasmparser::DataSectionReader<'_>, ) -> Result<(), Error> { utils::parse_data_section(self, data, section) } /// Parses a single [`wasmparser::Data`] and adds it to the `data` section. fn parse_data( &mut self, data: &mut crate::DataSection, datum: wasmparser::Data<'_>, ) -> Result<(), Error> { utils::parse_data(self, data, datum) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the elements to the `element` section. fn parse_element_section( &mut self, elements: &mut crate::ElementSection, section: wasmparser::ElementSectionReader<'_>, ) -> Result<(), Error> { utils::parse_element_section(self, elements, section) } /// Parses the single [`wasmparser::Element`] provided and adds it to the /// `element` section. fn parse_element( &mut self, elements: &mut crate::ElementSection, element: wasmparser::Element<'_>, ) -> Result<(), Error> { utils::parse_element(self, elements, element) } fn element_items<'a>( &mut self, items: wasmparser::ElementItems<'a>, ) -> Result, Error> { utils::element_items(self, items) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the exports to the `exports` section. fn parse_export_section( &mut self, exports: &mut crate::ExportSection, section: wasmparser::ExportSectionReader<'_>, ) -> Result<(), Error> { utils::parse_export_section(self, exports, section) } /// Parses the single [`wasmparser::Export`] provided and adds it to the /// `exports` section. fn parse_export(&mut self, exports: &mut crate::ExportSection, export: wasmparser::Export<'_>) { utils::parse_export(self, exports, export) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the functions to the `functions` section. fn parse_function_section( &mut self, functions: &mut crate::FunctionSection, section: wasmparser::FunctionSectionReader<'_>, ) -> Result<(), Error> { utils::parse_function_section(self, functions, section) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the globals to the `globals` section. fn parse_global_section( &mut self, globals: &mut crate::GlobalSection, section: wasmparser::GlobalSectionReader<'_>, ) -> Result<(), Error> { utils::parse_global_section(self, globals, section) } /// Parses the single [`wasmparser::Global`] provided and adds it to the /// `globals` section. fn parse_global( &mut self, globals: &mut crate::GlobalSection, global: wasmparser::Global<'_>, ) -> Result<(), Error> { utils::parse_global(self, globals, global) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the imports to the `import` section. fn parse_import_section( &mut self, imports: &mut crate::ImportSection, section: wasmparser::ImportSectionReader<'_>, ) -> Result<(), Error> { utils::parse_import_section(self, imports, section) } /// Parses the single [`wasmparser::Import`] provided and adds it to the /// `import` section. fn parse_import( &mut self, imports: &mut crate::ImportSection, import: wasmparser::Import<'_>, ) -> Result<(), Error> { utils::parse_import(self, imports, import) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the memories to the `memories` section. fn parse_memory_section( &mut self, memories: &mut crate::MemorySection, section: wasmparser::MemorySectionReader<'_>, ) -> Result<(), Error> { utils::parse_memory_section(self, memories, section) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the tables to the `tables` section. fn parse_table_section( &mut self, tables: &mut crate::TableSection, section: wasmparser::TableSectionReader<'_>, ) -> Result<(), Error> { utils::parse_table_section(self, tables, section) } /// Parses a single [`wasmparser::Table`] and adds it to the `tables` section. fn parse_table( &mut self, tables: &mut crate::TableSection, table: wasmparser::Table<'_>, ) -> Result<(), Error> { utils::parse_table(self, tables, table) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the tags to the `tags` section. fn parse_tag_section( &mut self, tags: &mut crate::TagSection, section: wasmparser::TagSectionReader<'_>, ) -> Result<(), Error> { utils::parse_tag_section(self, tags, section) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the types to the `types` section. fn parse_type_section( &mut self, types: &mut crate::TypeSection, section: wasmparser::TypeSectionReader<'_>, ) -> Result<(), Error> { utils::parse_type_section(self, types, section) } /// Parses a single [`wasmparser::RecGroup`] and adds it to the `types` section. fn parse_recursive_type_group( &mut self, encoder: CoreTypeEncoder, rec_group: wasmparser::RecGroup, ) -> Result<(), Error> { utils::parse_recursive_type_group(self, encoder, rec_group) } fn parse_unknown_section( &mut self, module: &mut crate::Module, id: u8, contents: &[u8], ) -> Result<(), Error> { utils::parse_unknown_section(self, module, id, contents) } /// A hook method that is called inside [`Reencode::parse_core_module`] /// before and after every non-custom core wasm section. /// /// This method can be used to insert new custom sections in between those /// sections, or to detect when a non-custom section is missing and insert /// it in the [proper order]. /// /// The `after` parameter is `None` iff the hook is called before the first /// non-custom section, and `Some(s)` afterwards, where `s` is the /// [`SectionId`] of the previous non-custom section. /// /// The `before` parameter is `None` iff the hook is called after the last /// non-custom section, and `Some(s)` beforehand, where `s` is the /// [`SectionId`] of the following non-custom section. /// /// [proper order]: https://webassembly.github.io/spec/core/binary/modules.html#binary-module /// [`SectionId`]: crate::SectionId fn intersperse_section_hook( &mut self, module: &mut crate::Module, after: Option, before: Option, ) -> Result<(), Error> { utils::intersperse_section_hook(self, module, after, before) } fn parse_core_module( &mut self, module: &mut crate::Module, parser: wasmparser::Parser, data: &[u8], ) -> Result<(), Error> { utils::parse_core_module(self, module, parser, data) } fn custom_name_section( &mut self, section: wasmparser::NameSectionReader<'_>, ) -> Result> { utils::custom_name_section(self, section) } fn parse_custom_name_subsection( &mut self, names: &mut crate::NameSection, section: wasmparser::Name<'_>, ) -> Result<(), Error> { utils::parse_custom_name_subsection(self, names, section) } fn data_count(&mut self, count: u32) -> u32 { count } fn start_section(&mut self, start: u32) -> u32 { self.function_index(start) } } /// An error when re-encoding from `wasmparser` to `wasm-encoder`. #[derive(Debug)] pub enum Error { /// There was a type reference that was canonicalized and no longer /// references an index into a module's types space, so we cannot encode it /// into a Wasm binary again. CanonicalizedHeapTypeReference, /// The const expression is invalid: not actually constant or something like /// that. InvalidConstExpr, /// The code section size listed was not valid for the wasm binary provided. InvalidCodeSectionSize, /// There was a section that does not belong into a core wasm module. UnexpectedNonCoreModuleSection, /// There was a section that does not belong into a compoennt module. UnexpectedNonComponentSection, /// A core type definition was found in a component that's not supported. UnsupportedCoreTypeInComponent, /// There was an error when parsing. ParseError(wasmparser::BinaryReaderError), /// There was a user-defined error when re-encoding. UserError(E), } impl From for Error { fn from(err: wasmparser::BinaryReaderError) -> Self { Self::ParseError(err) } } impl std::fmt::Display for Error { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Self::ParseError(_e) => { write!(fmt, "There was an error when parsing") } Self::UserError(e) => write!(fmt, "{e}"), Self::InvalidConstExpr => write!(fmt, "The const expression was invalid"), Self::UnexpectedNonCoreModuleSection => write!( fmt, "There was a section that does not belong into a core wasm module" ), Self::UnexpectedNonComponentSection => write!( fmt, "There was a section that does not belong into a component" ), Self::CanonicalizedHeapTypeReference => write!( fmt, "There was a canonicalized heap type reference without type index information" ), Self::UnsupportedCoreTypeInComponent => { fmt.write_str("unsupported core type in a component") } Self::InvalidCodeSectionSize => fmt.write_str("invalid code section size"), } } } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Self::ParseError(e) => Some(e), Self::UserError(e) => Some(e), Self::InvalidConstExpr | Self::CanonicalizedHeapTypeReference | Self::UnexpectedNonCoreModuleSection | Self::UnexpectedNonComponentSection | Self::UnsupportedCoreTypeInComponent | Self::InvalidCodeSectionSize => None, } } } /// Reencodes `wasmparser` into `wasm-encoder` so that the encoded wasm is /// identical to the input and can be parsed and encoded again. #[derive(Debug)] pub struct RoundtripReencoder; impl Reencode for RoundtripReencoder { type Error = Infallible; } #[allow(missing_docs)] // FIXME pub mod utils { use super::{Error, Reencode}; use crate::{CoreTypeEncoder, Encode}; use std::ops::Range; pub fn parse_core_module( reencoder: &mut T, module: &mut crate::Module, parser: wasmparser::Parser, data: &[u8], ) -> Result<(), Error> { fn handle_intersperse_section_hook( reencoder: &mut T, module: &mut crate::Module, last_section: &mut Option, next_section: Option, ) -> Result<(), Error> { let after = std::mem::replace(last_section, next_section); let before = next_section; reencoder.intersperse_section_hook(module, after, before) } // Convert from `range` to a byte range within `data` while // accounting for various offsets. Then create a // `CodeSectionReader` (which notably the payload does not // give us here) and recurse with that. This means that // users overridding `parse_code_section` always get that // function called. let orig_offset = parser.offset() as usize; let get_original_section = |range: Range| { data.get(range.start - orig_offset..range.end - orig_offset) .ok_or(Error::InvalidCodeSectionSize) }; let mut last_section = None; for section in parser.parse_all(data) { match section? { wasmparser::Payload::Version { encoding: wasmparser::Encoding::Module, .. } => (), wasmparser::Payload::Version { .. } => { return Err(Error::UnexpectedNonCoreModuleSection) } wasmparser::Payload::TypeSection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Type), )?; let mut types = crate::TypeSection::new(); reencoder.parse_type_section(&mut types, section)?; module.section(&types); } wasmparser::Payload::ImportSection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Import), )?; let mut imports = crate::ImportSection::new(); reencoder.parse_import_section(&mut imports, section)?; module.section(&imports); } wasmparser::Payload::FunctionSection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Function), )?; let mut functions = crate::FunctionSection::new(); reencoder.parse_function_section(&mut functions, section)?; module.section(&functions); } wasmparser::Payload::TableSection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Table), )?; let mut tables = crate::TableSection::new(); reencoder.parse_table_section(&mut tables, section)?; module.section(&tables); } wasmparser::Payload::MemorySection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Memory), )?; let mut memories = crate::MemorySection::new(); reencoder.parse_memory_section(&mut memories, section)?; module.section(&memories); } wasmparser::Payload::TagSection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Tag), )?; let mut tags = crate::TagSection::new(); reencoder.parse_tag_section(&mut tags, section)?; module.section(&tags); } wasmparser::Payload::GlobalSection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Global), )?; let mut globals = crate::GlobalSection::new(); reencoder.parse_global_section(&mut globals, section)?; module.section(&globals); } wasmparser::Payload::ExportSection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Export), )?; let mut exports = crate::ExportSection::new(); reencoder.parse_export_section(&mut exports, section)?; module.section(&exports); } wasmparser::Payload::StartSection { func, .. } => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Start), )?; module.section(&crate::StartSection { function_index: reencoder.start_section(func), }); } wasmparser::Payload::ElementSection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Element), )?; let mut elements = crate::ElementSection::new(); reencoder.parse_element_section(&mut elements, section)?; module.section(&elements); } wasmparser::Payload::DataCountSection { count, .. } => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::DataCount), )?; let count = reencoder.data_count(count); module.section(&crate::DataCountSection { count }); } wasmparser::Payload::DataSection(section) => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Data), )?; let mut data = crate::DataSection::new(); reencoder.parse_data_section(&mut data, section)?; module.section(&data); } wasmparser::Payload::CodeSectionStart { range, .. } => { handle_intersperse_section_hook( reencoder, module, &mut last_section, Some(crate::SectionId::Code), )?; let mut codes = crate::CodeSection::new(); // Convert from `range` to a byte range within `data` while // accounting for various offsets. Then create a // `CodeSectionReader` (which notably the payload does not // give us here) and recurse with that. This means that // users overridding `parse_code_section` always get that // function called. let section = get_original_section(range.clone())?; let reader = wasmparser::BinaryReader::new(section, range.start); let section = wasmparser::CodeSectionReader::new(reader)?; reencoder.parse_code_section(&mut codes, section)?; module.section(&codes); } // Parsing of code section entries (function bodies) happens // above during the handling of the code section. That means // that we just skip all these payloads. wasmparser::Payload::CodeSectionEntry(_) => {} #[cfg(feature = "component-model")] wasmparser::Payload::ModuleSection { .. } | wasmparser::Payload::InstanceSection(_) | wasmparser::Payload::CoreTypeSection(_) | wasmparser::Payload::ComponentSection { .. } | wasmparser::Payload::ComponentInstanceSection(_) | wasmparser::Payload::ComponentAliasSection(_) | wasmparser::Payload::ComponentTypeSection(_) | wasmparser::Payload::ComponentCanonicalSection(_) | wasmparser::Payload::ComponentStartSection { .. } | wasmparser::Payload::ComponentImportSection(_) | wasmparser::Payload::ComponentExportSection(_) => { return Err(Error::UnexpectedNonCoreModuleSection) } wasmparser::Payload::CustomSection(section) => { reencoder.parse_custom_section(module, section)?; } wasmparser::Payload::End(_) => { handle_intersperse_section_hook(reencoder, module, &mut last_section, None)?; } other => match other.as_section() { Some((id, range)) => { let section = get_original_section(range)?; reencoder.parse_unknown_section(module, id, section)?; } None => unreachable!(), }, } } Ok(()) } /// A hook method that is called inside [`Reencode::parse_core_module`] /// before and after every non-custom core wasm section. /// /// This method can be used to insert new custom sections in between those /// sections, or to detect when a non-custom section is missing and insert /// it in the [proper order]. /// /// The `after` parameter is `None` iff the hook is called before the first /// non-custom section, and `Some(s)` afterwards, where `s` is the /// [`SectionId`] of the previous non-custom section. /// /// The `before` parameter is `None` iff the hook is called after the last /// non-custom section, and `Some(s)` beforehand, where `s` is the /// [`SectionId`] of the following non-custom section. /// /// [proper order]: https://webassembly.github.io/spec/core/binary/modules.html#binary-module /// [`SectionId`]: crate::SectionId pub fn intersperse_section_hook( _reencoder: &mut T, _module: &mut crate::Module, _after: Option, _before: Option, ) -> Result<(), Error> { Ok(()) } pub fn memory_index(_reencoder: &mut T, memory: u32) -> u32 { memory } pub fn mem_arg( reencoder: &mut T, arg: wasmparser::MemArg, ) -> crate::MemArg { crate::MemArg { offset: arg.offset, align: arg.align.into(), memory_index: reencoder.memory_index(arg.memory), } } pub fn ordering( _reencoder: &mut T, arg: wasmparser::Ordering, ) -> crate::Ordering { match arg { wasmparser::Ordering::SeqCst => crate::Ordering::SeqCst, wasmparser::Ordering::AcqRel => crate::Ordering::AcqRel, } } pub fn function_index(_reencoder: &mut T, func: u32) -> u32 { func } pub fn tag_index(_reencoder: &mut T, tag: u32) -> u32 { tag } pub fn catch(reencoder: &mut T, arg: wasmparser::Catch) -> crate::Catch { match arg { wasmparser::Catch::One { tag, label } => crate::Catch::One { tag: reencoder.tag_index(tag), label, }, wasmparser::Catch::OneRef { tag, label } => crate::Catch::OneRef { tag: reencoder.tag_index(tag), label, }, wasmparser::Catch::All { label } => crate::Catch::All { label }, wasmparser::Catch::AllRef { label } => crate::Catch::AllRef { label }, } } pub fn handle( reencoder: &mut T, arg: wasmparser::Handle, ) -> crate::Handle { match arg { wasmparser::Handle::OnLabel { tag, label } => crate::Handle::OnLabel { tag: reencoder.tag_index(tag), label, }, wasmparser::Handle::OnSwitch { tag } => crate::Handle::OnSwitch { tag: reencoder.tag_index(tag), }, } } /// Parses the input `section` given from the `wasmparser` crate and /// adds the custom section to the `module`. pub fn parse_custom_section( reencoder: &mut T, module: &mut crate::Module, section: wasmparser::CustomSectionReader<'_>, ) -> Result<(), Error> { match section.as_known() { wasmparser::KnownCustom::Name(name) => { module.section(&reencoder.custom_name_section(name)?); } _ => { module.section(&reencoder.custom_section(section)); } } Ok(()) } /// Converts the input `section` given from the `wasmparser` crate into an /// encoded custom section. pub fn custom_section<'a, T: ?Sized + Reencode>( _reencoder: &mut T, section: wasmparser::CustomSectionReader<'a>, ) -> crate::CustomSection<'a> { crate::CustomSection { data: section.data().into(), name: section.name().into(), } } pub fn export_kind( _reencoder: &mut T, external_kind: wasmparser::ExternalKind, ) -> crate::ExportKind { match external_kind { wasmparser::ExternalKind::Func => crate::ExportKind::Func, wasmparser::ExternalKind::Table => crate::ExportKind::Table, wasmparser::ExternalKind::Memory => crate::ExportKind::Memory, wasmparser::ExternalKind::Global => crate::ExportKind::Global, wasmparser::ExternalKind::Tag => crate::ExportKind::Tag, } } pub fn memory_type( _reencoder: &mut T, memory_ty: wasmparser::MemoryType, ) -> crate::MemoryType { crate::MemoryType { minimum: memory_ty.initial, maximum: memory_ty.maximum, memory64: memory_ty.memory64, shared: memory_ty.shared, page_size_log2: memory_ty.page_size_log2, } } pub fn tag_kind( _reencoder: &mut T, kind: wasmparser::TagKind, ) -> crate::TagKind { match kind { wasmparser::TagKind::Exception => crate::TagKind::Exception, } } pub fn type_index(_reencoder: &mut T, ty: u32) -> u32 { ty } pub fn type_index_unpacked( reencoder: &mut T, ty: wasmparser::UnpackedIndex, ) -> Result> { ty.as_module_index() .map(|ty| reencoder.type_index(ty)) .ok_or(Error::CanonicalizedHeapTypeReference) } pub fn tag_type( reencoder: &mut T, tag_ty: wasmparser::TagType, ) -> crate::TagType { crate::TagType { kind: reencoder.tag_kind(tag_ty.kind), func_type_idx: reencoder.type_index(tag_ty.func_type_idx), } } pub fn abstract_heap_type( _reencoder: &mut T, value: wasmparser::AbstractHeapType, ) -> crate::AbstractHeapType { use wasmparser::AbstractHeapType::*; match value { Func => crate::AbstractHeapType::Func, Extern => crate::AbstractHeapType::Extern, Any => crate::AbstractHeapType::Any, None => crate::AbstractHeapType::None, NoExtern => crate::AbstractHeapType::NoExtern, NoFunc => crate::AbstractHeapType::NoFunc, Eq => crate::AbstractHeapType::Eq, Struct => crate::AbstractHeapType::Struct, Array => crate::AbstractHeapType::Array, I31 => crate::AbstractHeapType::I31, Exn => crate::AbstractHeapType::Exn, NoExn => crate::AbstractHeapType::NoExn, Cont => crate::AbstractHeapType::Cont, NoCont => crate::AbstractHeapType::NoCont, } } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the types to the `types` section. pub fn parse_type_section( reencoder: &mut T, types: &mut crate::TypeSection, section: wasmparser::TypeSectionReader<'_>, ) -> Result<(), Error> { for rec_group in section { reencoder.parse_recursive_type_group(types.ty(), rec_group?)?; } Ok(()) } /// Parses a single [`wasmparser::RecGroup`] and adds it to the `types` section. pub fn parse_recursive_type_group( reencoder: &mut T, encoder: CoreTypeEncoder, rec_group: wasmparser::RecGroup, ) -> Result<(), Error> { if rec_group.is_explicit_rec_group() { let subtypes = rec_group .into_types() .map(|t| reencoder.sub_type(t)) .collect::, _>>()?; encoder.rec(subtypes); } else { let ty = rec_group.into_types().next().unwrap(); encoder.subtype(&reencoder.sub_type(ty)?); } Ok(()) } pub fn sub_type( reencoder: &mut T, sub_ty: wasmparser::SubType, ) -> Result> { Ok(crate::SubType { is_final: sub_ty.is_final, supertype_idx: sub_ty .supertype_idx .map(|i| reencoder.type_index_unpacked(i.unpack())) .transpose()?, composite_type: reencoder.composite_type(sub_ty.composite_type)?, }) } pub fn composite_type( reencoder: &mut T, composite_ty: wasmparser::CompositeType, ) -> Result> { let inner = match composite_ty.inner { wasmparser::CompositeInnerType::Func(f) => { crate::CompositeInnerType::Func(reencoder.func_type(f)?) } wasmparser::CompositeInnerType::Array(a) => { crate::CompositeInnerType::Array(reencoder.array_type(a)?) } wasmparser::CompositeInnerType::Struct(s) => { crate::CompositeInnerType::Struct(reencoder.struct_type(s)?) } wasmparser::CompositeInnerType::Cont(c) => { crate::CompositeInnerType::Cont(reencoder.cont_type(c)?) } }; Ok(crate::CompositeType { inner, shared: composite_ty.shared, }) } pub fn func_type( reencoder: &mut T, func_ty: wasmparser::FuncType, ) -> Result> { let mut buf = Vec::with_capacity(func_ty.params().len() + func_ty.results().len()); for ty in func_ty.params().iter().chain(func_ty.results()).copied() { buf.push(reencoder.val_type(ty)?); } Ok(crate::FuncType::from_parts( buf.into(), func_ty.params().len(), )) } pub fn array_type( reencoder: &mut T, array_ty: wasmparser::ArrayType, ) -> Result> { Ok(crate::ArrayType(reencoder.field_type(array_ty.0)?)) } pub fn struct_type( reencoder: &mut T, struct_ty: wasmparser::StructType, ) -> Result> { Ok(crate::StructType { fields: struct_ty .fields .iter() .map(|field_ty| reencoder.field_type(*field_ty)) .collect::>()?, }) } pub fn field_type( reencoder: &mut T, field_ty: wasmparser::FieldType, ) -> Result> { Ok(crate::FieldType { element_type: reencoder.storage_type(field_ty.element_type)?, mutable: field_ty.mutable, }) } pub fn storage_type( reencoder: &mut T, storage_ty: wasmparser::StorageType, ) -> Result> { Ok(match storage_ty { wasmparser::StorageType::I8 => crate::StorageType::I8, wasmparser::StorageType::I16 => crate::StorageType::I16, wasmparser::StorageType::Val(v) => crate::StorageType::Val(reencoder.val_type(v)?), }) } pub fn cont_type( reencoder: &mut T, cont_ty: wasmparser::ContType, ) -> Result> { Ok(crate::ContType( reencoder.type_index_unpacked(cont_ty.0.unpack())?, )) } pub fn val_type( reencoder: &mut T, val_ty: wasmparser::ValType, ) -> Result> { Ok(match val_ty { wasmparser::ValType::I32 => crate::ValType::I32, wasmparser::ValType::I64 => crate::ValType::I64, wasmparser::ValType::F32 => crate::ValType::F32, wasmparser::ValType::F64 => crate::ValType::F64, wasmparser::ValType::V128 => crate::ValType::V128, wasmparser::ValType::Ref(r) => crate::ValType::Ref(reencoder.ref_type(r)?), }) } pub fn ref_type( reencoder: &mut T, ref_type: wasmparser::RefType, ) -> Result> { Ok(crate::RefType { nullable: ref_type.is_nullable(), heap_type: reencoder.heap_type(ref_type.heap_type())?, }) } pub fn heap_type( reencoder: &mut T, heap_type: wasmparser::HeapType, ) -> Result> { Ok(match heap_type { wasmparser::HeapType::Concrete(i) => { crate::HeapType::Concrete(reencoder.type_index_unpacked(i)?) } wasmparser::HeapType::Abstract { shared, ty } => crate::HeapType::Abstract { shared, ty: reencoder.abstract_heap_type(ty), }, }) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the tables to the `tables` section. pub fn parse_table_section( reencoder: &mut T, tables: &mut crate::TableSection, section: wasmparser::TableSectionReader<'_>, ) -> Result<(), Error> { for table in section { reencoder.parse_table(tables, table?)?; } Ok(()) } /// Parses a single [`wasmparser::Table`] and adds it to the `tables` section. pub fn parse_table( reencoder: &mut T, tables: &mut crate::TableSection, table: wasmparser::Table<'_>, ) -> Result<(), Error> { let ty = reencoder.table_type(table.ty)?; match table.init { wasmparser::TableInit::RefNull => { tables.table(ty); } wasmparser::TableInit::Expr(e) => { tables.table_with_init(ty, &reencoder.const_expr(e)?); } } Ok(()) } pub fn table_type( reencoder: &mut T, table_ty: wasmparser::TableType, ) -> Result> { Ok(crate::TableType { element_type: reencoder.ref_type(table_ty.element_type)?, minimum: table_ty.initial, maximum: table_ty.maximum, table64: table_ty.table64, shared: table_ty.shared, }) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the tags to the `tags` section. pub fn parse_tag_section( reencoder: &mut T, tags: &mut crate::TagSection, section: wasmparser::TagSectionReader<'_>, ) -> Result<(), Error> { for tag in section { let tag = tag?; tags.tag(reencoder.tag_type(tag)); } Ok(()) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the exports to the `exports` section. pub fn parse_export_section( reencoder: &mut T, exports: &mut crate::ExportSection, section: wasmparser::ExportSectionReader<'_>, ) -> Result<(), Error> { for export in section { reencoder.parse_export(exports, export?); } Ok(()) } /// Parses the single [`wasmparser::Export`] provided and adds it to the /// `exports` section. pub fn parse_export( reencoder: &mut T, exports: &mut crate::ExportSection, export: wasmparser::Export<'_>, ) { exports.export( export.name, reencoder.export_kind(export.kind), reencoder.external_index(export.kind, export.index), ); } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the globals to the `globals` section. pub fn parse_global_section( reencoder: &mut T, globals: &mut crate::GlobalSection, section: wasmparser::GlobalSectionReader<'_>, ) -> Result<(), Error> { for global in section { reencoder.parse_global(globals, global?)?; } Ok(()) } /// Parses the single [`wasmparser::Global`] provided and adds it to the /// `globals` section. pub fn parse_global( reencoder: &mut T, globals: &mut crate::GlobalSection, global: wasmparser::Global<'_>, ) -> Result<(), Error> { globals.global( reencoder.global_type(global.ty)?, &reencoder.const_expr(global.init_expr)?, ); Ok(()) } pub fn global_type( reencoder: &mut T, global_ty: wasmparser::GlobalType, ) -> Result> { Ok(crate::GlobalType { val_type: reencoder.val_type(global_ty.content_type)?, mutable: global_ty.mutable, shared: global_ty.shared, }) } pub fn entity_type( reencoder: &mut T, type_ref: wasmparser::TypeRef, ) -> Result> { Ok(match type_ref { wasmparser::TypeRef::Func(i) => crate::EntityType::Function(reencoder.type_index(i)), wasmparser::TypeRef::Table(t) => crate::EntityType::Table(reencoder.table_type(t)?), wasmparser::TypeRef::Memory(m) => crate::EntityType::Memory(reencoder.memory_type(m)), wasmparser::TypeRef::Global(g) => crate::EntityType::Global(reencoder.global_type(g)?), wasmparser::TypeRef::Tag(t) => crate::EntityType::Tag(reencoder.tag_type(t)), }) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the imports to the `import` section. pub fn parse_import_section( reencoder: &mut T, imports: &mut crate::ImportSection, section: wasmparser::ImportSectionReader<'_>, ) -> Result<(), Error> { for import in section { reencoder.parse_import(imports, import?)?; } Ok(()) } /// Parses the single [`wasmparser::Import`] provided and adds it to the /// `import` section. pub fn parse_import( reencoder: &mut T, imports: &mut crate::ImportSection, import: wasmparser::Import<'_>, ) -> Result<(), Error> { imports.import( import.module, import.name, reencoder.entity_type(import.ty)?, ); Ok(()) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the memories to the `memories` section. pub fn parse_memory_section( reencoder: &mut T, memories: &mut crate::MemorySection, section: wasmparser::MemorySectionReader<'_>, ) -> Result<(), Error> { for memory in section { let memory = memory?; memories.memory(reencoder.memory_type(memory)); } Ok(()) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the functions to the `functions` section. pub fn parse_function_section( reencoder: &mut T, functions: &mut crate::FunctionSection, section: wasmparser::FunctionSectionReader<'_>, ) -> Result<(), Error> { for func in section { functions.function(reencoder.type_index(func?)); } Ok(()) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the data to the `data` section. pub fn parse_data_section( reencoder: &mut T, data: &mut crate::DataSection, section: wasmparser::DataSectionReader<'_>, ) -> Result<(), Error> { for datum in section { reencoder.parse_data(data, datum?)?; } Ok(()) } /// Parses a single [`wasmparser::Data`] and adds it to the `data` section. pub fn parse_data( reencoder: &mut T, data: &mut crate::DataSection, datum: wasmparser::Data<'_>, ) -> Result<(), Error> { match datum.kind { wasmparser::DataKind::Active { memory_index, offset_expr, } => data.active( reencoder.memory_index(memory_index), &reencoder.const_expr(offset_expr)?, datum.data.iter().copied(), ), wasmparser::DataKind::Passive => data.passive(datum.data.iter().copied()), }; Ok(()) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the elements to the `element` section. pub fn parse_element_section( reencoder: &mut T, elements: &mut crate::ElementSection, section: wasmparser::ElementSectionReader<'_>, ) -> Result<(), Error> { for element in section { reencoder.parse_element(elements, element?)?; } Ok(()) } /// Parses the single [`wasmparser::Element`] provided and adds it to the /// `element` section. pub fn parse_element( reencoder: &mut T, elements: &mut crate::ElementSection, element: wasmparser::Element<'_>, ) -> Result<(), Error> { let elems = reencoder.element_items(element.items)?; match element.kind { wasmparser::ElementKind::Active { table_index, offset_expr, } => elements.active( // Inform the reencoder that a table index is being used even if // it's not actually present here. That helps wasm-mutate for // example which wants to track uses to know when it's ok to // remove a table. // // If the table index started at `None` and is still zero then // preserve this encoding and keep it at `None`. Otherwise if // the result is nonzero or it was previously nonzero then keep // that encoding too. match (table_index, reencoder.table_index(table_index.unwrap_or(0))) { (None, 0) => None, (_, n) => Some(n), }, &reencoder.const_expr(offset_expr)?, elems, ), wasmparser::ElementKind::Passive => elements.passive(elems), wasmparser::ElementKind::Declared => elements.declared(elems), }; Ok(()) } pub fn element_items<'a, T: ?Sized + Reencode>( reencoder: &mut T, items: wasmparser::ElementItems<'a>, ) -> Result, Error> { Ok(match items { wasmparser::ElementItems::Functions(f) => { let mut funcs = Vec::new(); for func in f { funcs.push(reencoder.function_index(func?)); } crate::Elements::Functions(funcs.into()) } wasmparser::ElementItems::Expressions(ty, e) => { let mut exprs = Vec::new(); for expr in e { exprs.push(reencoder.const_expr(expr?)?); } crate::Elements::Expressions(reencoder.ref_type(ty)?, exprs.into()) } }) } pub fn table_index(_reencoder: &mut T, table: u32) -> u32 { table } pub fn global_index(_reencoder: &mut T, global: u32) -> u32 { global } pub fn data_index(_reencoder: &mut T, data: u32) -> u32 { data } pub fn element_index(_reencoder: &mut T, element: u32) -> u32 { element } pub fn const_expr( reencoder: &mut T, const_expr: wasmparser::ConstExpr, ) -> Result> { let mut ops = const_expr.get_operators_reader(); let mut bytes = Vec::new(); while !ops.is_end_then_eof() { let insn = reencoder.parse_instruction(&mut ops)?; insn.encode(&mut bytes); } Ok(crate::ConstExpr::raw(bytes)) } pub fn block_type( reencoder: &mut T, arg: wasmparser::BlockType, ) -> Result> { match arg { wasmparser::BlockType::Empty => Ok(crate::BlockType::Empty), wasmparser::BlockType::FuncType(n) => { Ok(crate::BlockType::FunctionType(reencoder.type_index(n))) } wasmparser::BlockType::Type(t) => Ok(crate::BlockType::Result(reencoder.val_type(t)?)), } } pub fn instruction<'a, T: ?Sized + Reencode>( reencoder: &mut T, arg: wasmparser::Operator<'a>, ) -> Result, Error> { use crate::Instruction; macro_rules! translate { ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => { Ok(match arg { $( wasmparser::Operator::$op $({ $($arg),* })? => { $( $(let $arg = translate!(map $arg $arg);)* )? translate!(build $op $($($arg)*)?) } )* unexpected => unreachable!("encountered unexpected Wasm operator: {unexpected:?}"), }) }; // This case is used to map, based on the name of the field, from the // wasmparser payload type to the wasm-encoder payload type through // `Translator` as applicable. (map $arg:ident tag_index) => (reencoder.tag_index($arg)); (map $arg:ident function_index) => (reencoder.function_index($arg)); (map $arg:ident table) => (reencoder.table_index($arg)); (map $arg:ident table_index) => (reencoder.table_index($arg)); (map $arg:ident dst_table) => (reencoder.table_index($arg)); (map $arg:ident src_table) => (reencoder.table_index($arg)); (map $arg:ident type_index) => (reencoder.type_index($arg)); (map $arg:ident array_type_index) => (reencoder.type_index($arg)); (map $arg:ident array_type_index_dst) => (reencoder.type_index($arg)); (map $arg:ident array_type_index_src) => (reencoder.type_index($arg)); (map $arg:ident struct_type_index) => (reencoder.type_index($arg)); (map $arg:ident global_index) => (reencoder.global_index($arg)); (map $arg:ident mem) => (reencoder.memory_index($arg)); (map $arg:ident src_mem) => (reencoder.memory_index($arg)); (map $arg:ident dst_mem) => (reencoder.memory_index($arg)); (map $arg:ident data_index) => (reencoder.data_index($arg)); (map $arg:ident elem_index) => (reencoder.element_index($arg)); (map $arg:ident array_data_index) => (reencoder.data_index($arg)); (map $arg:ident array_elem_index) => (reencoder.element_index($arg)); (map $arg:ident blockty) => (reencoder.block_type($arg)?); (map $arg:ident relative_depth) => ($arg); (map $arg:ident targets) => (( $arg .targets() .collect::, wasmparser::BinaryReaderError>>()? .into(), $arg.default(), )); (map $arg:ident ty) => (reencoder.val_type($arg)?); (map $arg:ident hty) => (reencoder.heap_type($arg)?); (map $arg:ident from_ref_type) => (reencoder.ref_type($arg)?); (map $arg:ident to_ref_type) => (reencoder.ref_type($arg)?); (map $arg:ident memarg) => (reencoder.mem_arg($arg)); (map $arg:ident ordering) => (reencoder.ordering($arg)); (map $arg:ident local_index) => ($arg); (map $arg:ident value) => ($arg); (map $arg:ident lane) => ($arg); (map $arg:ident lanes) => ($arg); (map $arg:ident array_size) => ($arg); (map $arg:ident field_index) => ($arg); (map $arg:ident try_table) => ($arg); (map $arg:ident argument_index) => (reencoder.type_index($arg)); (map $arg:ident result_index) => (reencoder.type_index($arg)); (map $arg:ident cont_type_index) => (reencoder.type_index($arg)); (map $arg:ident resume_table) => (( $arg.handlers.into_iter().map(|h| reencoder.handle(h)).collect::>().into() )); // This case takes the arguments of a wasmparser instruction and creates // a wasm-encoder instruction. There are a few special cases for where // the structure of a wasmparser instruction differs from that of // wasm-encoder. (build $op:ident) => (Instruction::$op); (build BrTable $arg:ident) => (Instruction::BrTable($arg.0, $arg.1)); (build I32Const $arg:ident) => (Instruction::I32Const($arg)); (build I64Const $arg:ident) => (Instruction::I64Const($arg)); (build F32Const $arg:ident) => (Instruction::F32Const(f32::from_bits($arg.bits()))); (build F64Const $arg:ident) => (Instruction::F64Const(f64::from_bits($arg.bits()))); (build V128Const $arg:ident) => (Instruction::V128Const($arg.i128())); (build TryTable $table:ident) => (Instruction::TryTable(reencoder.block_type($table.ty)?, { $table.catches.into_iter().map(|c| reencoder.catch(c)).collect::>().into() })); (build $op:ident $arg:ident) => (Instruction::$op($arg)); (build $op:ident $($arg:ident)*) => (Instruction::$op { $($arg),* }); } wasmparser::for_each_operator!(translate) } /// Parses the input `section` given from the `wasmparser` crate and adds /// all the code to the `code` section. pub fn parse_code_section( reencoder: &mut T, code: &mut crate::CodeSection, section: wasmparser::CodeSectionReader<'_>, ) -> Result<(), Error> { for func in section { reencoder.parse_function_body(code, func?)?; } Ok(()) } /// Parses a single [`wasmparser::FunctionBody`] and adds it to the `code` section. pub fn parse_function_body( reencoder: &mut T, code: &mut crate::CodeSection, func: wasmparser::FunctionBody<'_>, ) -> Result<(), Error> { let mut f = reencoder.new_function_with_parsed_locals(&func)?; let mut reader = func.get_operators_reader()?; while !reader.eof() { f.instruction(&reencoder.parse_instruction(&mut reader)?); } code.function(&f); Ok(()) } /// Create a new [`crate::Function`] by parsing the locals declarations from the /// provided [`wasmparser::FunctionBody`]. pub fn new_function_with_parsed_locals( reencoder: &mut T, func: &wasmparser::FunctionBody<'_>, ) -> Result> { let mut locals = Vec::new(); for pair in func.get_locals_reader()? { let (cnt, ty) = pair?; locals.push((cnt, reencoder.val_type(ty)?)); } Ok(crate::Function::new(locals)) } /// Parses a single instruction from `reader` and adds it to `function`. pub fn parse_instruction<'a, T: ?Sized + Reencode>( reencoder: &mut T, reader: &mut wasmparser::OperatorsReader<'a>, ) -> Result, Error> { let instruction = reencoder.instruction(reader.read()?)?; Ok(instruction) } pub fn parse_unknown_section( _reencoder: &mut T, module: &mut crate::Module, id: u8, contents: &[u8], ) -> Result<(), Error> { module.section(&crate::RawSection { id, data: contents }); Ok(()) } pub fn custom_name_section( reencoder: &mut T, section: wasmparser::NameSectionReader<'_>, ) -> Result> { let mut ret = crate::NameSection::new(); for subsection in section { reencoder.parse_custom_name_subsection(&mut ret, subsection?)?; } Ok(ret) } pub fn parse_custom_name_subsection( reencoder: &mut T, names: &mut crate::NameSection, section: wasmparser::Name<'_>, ) -> Result<(), Error> { match section { wasmparser::Name::Module { name, .. } => { names.module(name); } wasmparser::Name::Function(map) => { names.functions(&name_map(map, |i| reencoder.function_index(i))?); } wasmparser::Name::Type(map) => { names.types(&name_map(map, |i| reencoder.type_index(i))?); } wasmparser::Name::Local(map) => { names.locals(&indirect_name_map(map, |i| reencoder.function_index(i))?); } wasmparser::Name::Label(map) => { names.labels(&indirect_name_map(map, |i| reencoder.function_index(i))?); } wasmparser::Name::Table(map) => { names.tables(&name_map(map, |i| reencoder.table_index(i))?); } wasmparser::Name::Memory(map) => { names.memories(&name_map(map, |i| reencoder.memory_index(i))?); } wasmparser::Name::Global(map) => { names.globals(&name_map(map, |i| reencoder.global_index(i))?); } wasmparser::Name::Element(map) => { names.elements(&name_map(map, |i| reencoder.element_index(i))?); } wasmparser::Name::Data(map) => { names.data(&name_map(map, |i| reencoder.data_index(i))?); } wasmparser::Name::Tag(map) => { names.tags(&name_map(map, |i| reencoder.tag_index(i))?); } wasmparser::Name::Field(map) => { names.fields(&indirect_name_map(map, |i| reencoder.type_index(i))?); } wasmparser::Name::Unknown { ty, data, .. } => { names.raw(ty, data); } } Ok(()) } pub fn name_map( map: wasmparser::NameMap<'_>, mut map_index: impl FnMut(u32) -> u32, ) -> wasmparser::Result { let mut ret = crate::NameMap::new(); for naming in map { let naming = naming?; ret.append(map_index(naming.index), naming.name); } Ok(ret) } pub fn indirect_name_map( map: wasmparser::IndirectNameMap<'_>, mut map_index: impl FnMut(u32) -> u32, ) -> wasmparser::Result { let mut ret = crate::IndirectNameMap::new(); for naming in map { let naming = naming?; ret.append(map_index(naming.index), &name_map(naming.names, |i| i)?); } Ok(ret) } } impl From for crate::MemArg { fn from(arg: wasmparser::MemArg) -> Self { RoundtripReencoder.mem_arg(arg) } } impl From for crate::Ordering { fn from(arg: wasmparser::Ordering) -> Self { RoundtripReencoder.ordering(arg) } } impl TryFrom for crate::BlockType { type Error = Error; fn try_from(arg: wasmparser::BlockType) -> Result { RoundtripReencoder.block_type(arg) } } impl<'a> TryFrom> for crate::Instruction<'a> { type Error = Error; fn try_from(arg: wasmparser::Operator<'a>) -> Result { RoundtripReencoder.instruction(arg) } } impl From for crate::Catch { fn from(arg: wasmparser::Catch) -> Self { RoundtripReencoder.catch(arg) } } impl<'a> TryFrom> for crate::ConstExpr { type Error = Error; fn try_from(const_expr: wasmparser::ConstExpr) -> Result { RoundtripReencoder.const_expr(const_expr) } } impl<'a> From> for crate::CustomSection<'a> { fn from(section: wasmparser::CustomSectionReader<'a>) -> Self { RoundtripReencoder.custom_section(section) } } impl From for crate::ExportKind { fn from(external_kind: wasmparser::ExternalKind) -> Self { RoundtripReencoder.export_kind(external_kind) } } impl TryFrom for crate::GlobalType { type Error = Error; fn try_from(global_ty: wasmparser::GlobalType) -> Result { RoundtripReencoder.global_type(global_ty) } } impl From for crate::Handle { fn from(arg: wasmparser::Handle) -> Self { RoundtripReencoder.handle(arg) } } impl TryFrom for crate::EntityType { type Error = Error; fn try_from(type_ref: wasmparser::TypeRef) -> Result { RoundtripReencoder.entity_type(type_ref) } } impl From for crate::MemoryType { fn from(memory_ty: wasmparser::MemoryType) -> Self { RoundtripReencoder.memory_type(memory_ty) } } impl TryFrom for crate::TableType { type Error = Error; fn try_from(table_ty: wasmparser::TableType) -> Result { RoundtripReencoder.table_type(table_ty) } } impl From for crate::TagKind { fn from(kind: wasmparser::TagKind) -> Self { RoundtripReencoder.tag_kind(kind) } } impl From for crate::TagType { fn from(tag_ty: wasmparser::TagType) -> Self { RoundtripReencoder.tag_type(tag_ty) } } impl TryFrom for crate::SubType { type Error = Error; fn try_from(sub_ty: wasmparser::SubType) -> Result { RoundtripReencoder.sub_type(sub_ty) } } impl TryFrom for crate::CompositeType { type Error = Error; fn try_from(composite_ty: wasmparser::CompositeType) -> Result { RoundtripReencoder.composite_type(composite_ty) } } impl TryFrom for crate::FuncType { type Error = Error; fn try_from(func_ty: wasmparser::FuncType) -> Result { RoundtripReencoder.func_type(func_ty) } } impl TryFrom for crate::ArrayType { type Error = Error; fn try_from(array_ty: wasmparser::ArrayType) -> Result { RoundtripReencoder.array_type(array_ty) } } impl TryFrom for crate::StructType { type Error = Error; fn try_from(struct_ty: wasmparser::StructType) -> Result { RoundtripReencoder.struct_type(struct_ty) } } impl TryFrom for crate::FieldType { type Error = Error; fn try_from(field_ty: wasmparser::FieldType) -> Result { RoundtripReencoder.field_type(field_ty) } } impl TryFrom for crate::StorageType { type Error = Error; fn try_from(storage_ty: wasmparser::StorageType) -> Result { RoundtripReencoder.storage_type(storage_ty) } } impl TryFrom for crate::ValType { type Error = Error; fn try_from(val_ty: wasmparser::ValType) -> Result { RoundtripReencoder.val_type(val_ty) } } impl TryFrom for crate::RefType { type Error = Error; fn try_from(ref_type: wasmparser::RefType) -> Result { RoundtripReencoder.ref_type(ref_type) } } impl TryFrom for crate::HeapType { type Error = Error; fn try_from(heap_type: wasmparser::HeapType) -> Result { crate::reencode::utils::heap_type(&mut crate::reencode::RoundtripReencoder, heap_type) } } impl From for crate::AbstractHeapType { fn from(value: wasmparser::AbstractHeapType) -> Self { RoundtripReencoder.abstract_heap_type(value) } }