wasm_encoder/
reencode.rs

1//! Conversions from `wasmparser` to `wasm-encoder` to [`Reencode`] parsed wasm.
2//!
3//! The [`RoundtripReencoder`] allows encoding identical wasm to the parsed
4//! input.
5
6#[cfg(all(not(feature = "std"), core_error))]
7use core::error::Error as StdError;
8#[cfg(feature = "std")]
9use std::error::Error as StdError;
10
11use crate::CoreTypeEncoder;
12use core::convert::Infallible;
13
14#[cfg(feature = "component-model")]
15mod component;
16
17#[cfg(feature = "component-model")]
18pub use self::component::*;
19
20#[cfg(feature = "wasmparser")]
21use alloc::vec::Vec;
22
23#[allow(missing_docs)] // FIXME
24pub trait Reencode {
25    type Error;
26
27    fn data_index(&mut self, data: u32) -> u32 {
28        utils::data_index(self, data)
29    }
30
31    fn element_index(&mut self, element: u32) -> u32 {
32        utils::element_index(self, element)
33    }
34
35    fn function_index(&mut self, func: u32) -> u32 {
36        utils::function_index(self, func)
37    }
38
39    fn global_index(&mut self, global: u32) -> u32 {
40        utils::global_index(self, global)
41    }
42
43    fn memory_index(&mut self, memory: u32) -> u32 {
44        utils::memory_index(self, memory)
45    }
46
47    fn table_index(&mut self, table: u32) -> u32 {
48        utils::table_index(self, table)
49    }
50
51    fn tag_index(&mut self, tag: u32) -> u32 {
52        utils::tag_index(self, tag)
53    }
54
55    fn type_index(&mut self, ty: u32) -> u32 {
56        utils::type_index(self, ty)
57    }
58
59    fn type_index_unpacked(
60        &mut self,
61        ty: wasmparser::UnpackedIndex,
62    ) -> Result<u32, Error<Self::Error>> {
63        utils::type_index_unpacked(self, ty)
64    }
65
66    fn external_index(&mut self, kind: wasmparser::ExternalKind, index: u32) -> u32 {
67        match kind {
68            wasmparser::ExternalKind::Func => self.function_index(index),
69            wasmparser::ExternalKind::Table => self.table_index(index),
70            wasmparser::ExternalKind::Memory => self.memory_index(index),
71            wasmparser::ExternalKind::Global => self.global_index(index),
72            wasmparser::ExternalKind::Tag => self.tag_index(index),
73        }
74    }
75
76    fn abstract_heap_type(
77        &mut self,
78        value: wasmparser::AbstractHeapType,
79    ) -> crate::AbstractHeapType {
80        utils::abstract_heap_type(self, value)
81    }
82
83    fn array_type(
84        &mut self,
85        array_ty: wasmparser::ArrayType,
86    ) -> Result<crate::ArrayType, Error<Self::Error>> {
87        utils::array_type(self, array_ty)
88    }
89
90    fn block_type(
91        &mut self,
92        arg: wasmparser::BlockType,
93    ) -> Result<crate::BlockType, Error<Self::Error>> {
94        utils::block_type(self, arg)
95    }
96
97    fn const_expr(
98        &mut self,
99        const_expr: wasmparser::ConstExpr,
100    ) -> Result<crate::ConstExpr, Error<Self::Error>> {
101        utils::const_expr(self, const_expr)
102    }
103
104    fn catch(&mut self, arg: wasmparser::Catch) -> crate::Catch {
105        utils::catch(self, arg)
106    }
107
108    fn composite_type(
109        &mut self,
110        composite_ty: wasmparser::CompositeType,
111    ) -> Result<crate::CompositeType, Error<Self::Error>> {
112        utils::composite_type(self, composite_ty)
113    }
114
115    fn entity_type(
116        &mut self,
117        type_ref: wasmparser::TypeRef,
118    ) -> Result<crate::EntityType, Error<Self::Error>> {
119        utils::entity_type(self, type_ref)
120    }
121
122    fn export_kind(&mut self, external_kind: wasmparser::ExternalKind) -> crate::ExportKind {
123        utils::export_kind(self, external_kind)
124    }
125
126    fn field_type(
127        &mut self,
128        field_ty: wasmparser::FieldType,
129    ) -> Result<crate::FieldType, Error<Self::Error>> {
130        utils::field_type(self, field_ty)
131    }
132
133    fn func_type(
134        &mut self,
135        func_ty: wasmparser::FuncType,
136    ) -> Result<crate::FuncType, Error<Self::Error>> {
137        utils::func_type(self, func_ty)
138    }
139
140    fn cont_type(
141        &mut self,
142        cont_ty: wasmparser::ContType,
143    ) -> Result<crate::ContType, Error<Self::Error>> {
144        utils::cont_type(self, cont_ty)
145    }
146
147    fn global_type(
148        &mut self,
149        global_ty: wasmparser::GlobalType,
150    ) -> Result<crate::GlobalType, Error<Self::Error>> {
151        utils::global_type(self, global_ty)
152    }
153
154    fn handle(&mut self, on: wasmparser::Handle) -> crate::Handle {
155        utils::handle(self, on)
156    }
157
158    fn heap_type(
159        &mut self,
160        heap_type: wasmparser::HeapType,
161    ) -> Result<crate::HeapType, Error<Self::Error>> {
162        utils::heap_type(self, heap_type)
163    }
164
165    fn instruction<'a>(
166        &mut self,
167        arg: wasmparser::Operator<'a>,
168    ) -> Result<crate::Instruction<'a>, Error<Self::Error>> {
169        utils::instruction(self, arg)
170    }
171
172    fn memory_type(&mut self, memory_ty: wasmparser::MemoryType) -> crate::MemoryType {
173        utils::memory_type(self, memory_ty)
174    }
175
176    fn ieee32_arg(&mut self, arg: wasmparser::Ieee32) -> crate::Ieee32 {
177        utils::ieee32_arg(self, arg)
178    }
179
180    fn ieee64_arg(&mut self, arg: wasmparser::Ieee64) -> crate::Ieee64 {
181        utils::ieee64_arg(self, arg)
182    }
183
184    fn mem_arg(&mut self, arg: wasmparser::MemArg) -> crate::MemArg {
185        utils::mem_arg(self, arg)
186    }
187
188    fn ordering(&mut self, arg: wasmparser::Ordering) -> crate::Ordering {
189        utils::ordering(self, arg)
190    }
191
192    fn ref_type(
193        &mut self,
194        ref_type: wasmparser::RefType,
195    ) -> Result<crate::RefType, Error<Self::Error>> {
196        utils::ref_type(self, ref_type)
197    }
198
199    fn storage_type(
200        &mut self,
201        storage_ty: wasmparser::StorageType,
202    ) -> Result<crate::StorageType, Error<Self::Error>> {
203        utils::storage_type(self, storage_ty)
204    }
205
206    fn struct_type(
207        &mut self,
208        struct_ty: wasmparser::StructType,
209    ) -> Result<crate::StructType, Error<Self::Error>> {
210        utils::struct_type(self, struct_ty)
211    }
212
213    fn sub_type(
214        &mut self,
215        sub_ty: wasmparser::SubType,
216    ) -> Result<crate::SubType, Error<Self::Error>> {
217        utils::sub_type(self, sub_ty)
218    }
219
220    fn table_type(
221        &mut self,
222        table_ty: wasmparser::TableType,
223    ) -> Result<crate::TableType, Error<Self::Error>> {
224        utils::table_type(self, table_ty)
225    }
226
227    fn tag_kind(&mut self, kind: wasmparser::TagKind) -> crate::TagKind {
228        utils::tag_kind(self, kind)
229    }
230
231    fn tag_type(&mut self, tag_ty: wasmparser::TagType) -> crate::TagType {
232        utils::tag_type(self, tag_ty)
233    }
234
235    fn val_type(
236        &mut self,
237        val_ty: wasmparser::ValType,
238    ) -> Result<crate::ValType, Error<Self::Error>> {
239        utils::val_type(self, val_ty)
240    }
241
242    fn val_types(
243        &mut self,
244        val_tys: Vec<wasmparser::ValType>,
245    ) -> Result<Vec<crate::ValType>, Error<Self::Error>> {
246        val_tys
247            .iter()
248            .map(|ty| utils::val_type(self, *ty))
249            .collect()
250    }
251
252    /// Parses the input `section` given from the `wasmparser` crate and
253    /// adds the custom section to the `module`.
254    fn parse_custom_section(
255        &mut self,
256        module: &mut crate::Module,
257        section: wasmparser::CustomSectionReader<'_>,
258    ) -> Result<(), Error<Self::Error>> {
259        utils::parse_custom_section(self, module, section)
260    }
261
262    /// Converts the input `section` given from the `wasmparser` crate into an
263    /// encoded custom section.
264    fn custom_section<'a>(
265        &mut self,
266        section: wasmparser::CustomSectionReader<'a>,
267    ) -> crate::CustomSection<'a> {
268        utils::custom_section(self, section)
269    }
270
271    /// Parses the input `section` given from the `wasmparser` crate and adds
272    /// all the code to the `code` section.
273    fn parse_code_section(
274        &mut self,
275        code: &mut crate::CodeSection,
276        section: wasmparser::CodeSectionReader<'_>,
277    ) -> Result<(), Error<Self::Error>> {
278        utils::parse_code_section(self, code, section)
279    }
280
281    /// Parses a single [`wasmparser::FunctionBody`] and adds it to the `code` section.
282    fn parse_function_body(
283        &mut self,
284        code: &mut crate::CodeSection,
285        func: wasmparser::FunctionBody<'_>,
286    ) -> Result<(), Error<Self::Error>> {
287        utils::parse_function_body(self, code, func)
288    }
289
290    /// Create a new [`crate::Function`] by parsing the locals declarations from the
291    /// provided [`wasmparser::FunctionBody`].
292    fn new_function_with_parsed_locals(
293        &mut self,
294        func: &wasmparser::FunctionBody<'_>,
295    ) -> Result<crate::Function, Error<Self::Error>> {
296        utils::new_function_with_parsed_locals(self, func)
297    }
298
299    /// Parses a single instruction from `reader` and adds it to `function`.
300    fn parse_instruction<'a>(
301        &mut self,
302        reader: &mut wasmparser::OperatorsReader<'a>,
303    ) -> Result<crate::Instruction<'a>, Error<Self::Error>> {
304        utils::parse_instruction(self, reader)
305    }
306
307    /// Parses the input `section` given from the `wasmparser` crate and adds
308    /// all the data to the `data` section.
309    fn parse_data_section(
310        &mut self,
311        data: &mut crate::DataSection,
312        section: wasmparser::DataSectionReader<'_>,
313    ) -> Result<(), Error<Self::Error>> {
314        utils::parse_data_section(self, data, section)
315    }
316
317    /// Parses a single [`wasmparser::Data`] and adds it to the `data` section.
318    fn parse_data(
319        &mut self,
320        data: &mut crate::DataSection,
321        datum: wasmparser::Data<'_>,
322    ) -> Result<(), Error<Self::Error>> {
323        utils::parse_data(self, data, datum)
324    }
325
326    /// Parses the input `section` given from the `wasmparser` crate and adds
327    /// all the elements to the `element` section.
328    fn parse_element_section(
329        &mut self,
330        elements: &mut crate::ElementSection,
331        section: wasmparser::ElementSectionReader<'_>,
332    ) -> Result<(), Error<Self::Error>> {
333        utils::parse_element_section(self, elements, section)
334    }
335
336    /// Parses the single [`wasmparser::Element`] provided and adds it to the
337    /// `element` section.
338    fn parse_element(
339        &mut self,
340        elements: &mut crate::ElementSection,
341        element: wasmparser::Element<'_>,
342    ) -> Result<(), Error<Self::Error>> {
343        utils::parse_element(self, elements, element)
344    }
345
346    fn element_items<'a>(
347        &mut self,
348        items: wasmparser::ElementItems<'a>,
349    ) -> Result<crate::Elements<'a>, Error<Self::Error>> {
350        utils::element_items(self, items)
351    }
352
353    /// Parses the input `section` given from the `wasmparser` crate and adds
354    /// all the exports to the `exports` section.
355    fn parse_export_section(
356        &mut self,
357        exports: &mut crate::ExportSection,
358        section: wasmparser::ExportSectionReader<'_>,
359    ) -> Result<(), Error<Self::Error>> {
360        utils::parse_export_section(self, exports, section)
361    }
362
363    /// Parses the single [`wasmparser::Export`] provided and adds it to the
364    /// `exports` section.
365    fn parse_export(&mut self, exports: &mut crate::ExportSection, export: wasmparser::Export<'_>) {
366        utils::parse_export(self, exports, export)
367    }
368
369    /// Parses the input `section` given from the `wasmparser` crate and adds
370    /// all the functions to the `functions` section.
371    fn parse_function_section(
372        &mut self,
373        functions: &mut crate::FunctionSection,
374        section: wasmparser::FunctionSectionReader<'_>,
375    ) -> Result<(), Error<Self::Error>> {
376        utils::parse_function_section(self, functions, section)
377    }
378
379    /// Parses the input `section` given from the `wasmparser` crate and adds
380    /// all the globals to the `globals` section.
381    fn parse_global_section(
382        &mut self,
383        globals: &mut crate::GlobalSection,
384        section: wasmparser::GlobalSectionReader<'_>,
385    ) -> Result<(), Error<Self::Error>> {
386        utils::parse_global_section(self, globals, section)
387    }
388
389    /// Parses the single [`wasmparser::Global`] provided and adds it to the
390    /// `globals` section.
391    fn parse_global(
392        &mut self,
393        globals: &mut crate::GlobalSection,
394        global: wasmparser::Global<'_>,
395    ) -> Result<(), Error<Self::Error>> {
396        utils::parse_global(self, globals, global)
397    }
398
399    /// Parses the input `section` given from the `wasmparser` crate and adds
400    /// all the imports to the `import` section.
401    fn parse_import_section(
402        &mut self,
403        imports: &mut crate::ImportSection,
404        section: wasmparser::ImportSectionReader<'_>,
405    ) -> Result<(), Error<Self::Error>> {
406        utils::parse_import_section(self, imports, section)
407    }
408
409    /// Parses the single [`wasmparser::Import`] provided and adds it to the
410    /// `import` section.
411    fn parse_import(
412        &mut self,
413        imports: &mut crate::ImportSection,
414        import: wasmparser::Import<'_>,
415    ) -> Result<(), Error<Self::Error>> {
416        utils::parse_import(self, imports, import)
417    }
418
419    /// Parses the input `section` given from the `wasmparser` crate and adds
420    /// all the memories to the `memories` section.
421    fn parse_memory_section(
422        &mut self,
423        memories: &mut crate::MemorySection,
424        section: wasmparser::MemorySectionReader<'_>,
425    ) -> Result<(), Error<Self::Error>> {
426        utils::parse_memory_section(self, memories, section)
427    }
428
429    /// Parses the input `section` given from the `wasmparser` crate and adds
430    /// all the tables to the `tables` section.
431    fn parse_table_section(
432        &mut self,
433        tables: &mut crate::TableSection,
434        section: wasmparser::TableSectionReader<'_>,
435    ) -> Result<(), Error<Self::Error>> {
436        utils::parse_table_section(self, tables, section)
437    }
438
439    /// Parses a single [`wasmparser::Table`] and adds it to the `tables` section.
440    fn parse_table(
441        &mut self,
442        tables: &mut crate::TableSection,
443        table: wasmparser::Table<'_>,
444    ) -> Result<(), Error<Self::Error>> {
445        utils::parse_table(self, tables, table)
446    }
447
448    /// Parses the input `section` given from the `wasmparser` crate and adds
449    /// all the tags to the `tags` section.
450    fn parse_tag_section(
451        &mut self,
452        tags: &mut crate::TagSection,
453        section: wasmparser::TagSectionReader<'_>,
454    ) -> Result<(), Error<Self::Error>> {
455        utils::parse_tag_section(self, tags, section)
456    }
457
458    /// Parses the input `section` given from the `wasmparser` crate and adds
459    /// all the types to the `types` section.
460    fn parse_type_section(
461        &mut self,
462        types: &mut crate::TypeSection,
463        section: wasmparser::TypeSectionReader<'_>,
464    ) -> Result<(), Error<Self::Error>> {
465        utils::parse_type_section(self, types, section)
466    }
467
468    /// Parses a single [`wasmparser::RecGroup`] and adds it to the `types` section.
469    fn parse_recursive_type_group(
470        &mut self,
471        encoder: CoreTypeEncoder,
472        rec_group: wasmparser::RecGroup,
473    ) -> Result<(), Error<Self::Error>> {
474        utils::parse_recursive_type_group(self, encoder, rec_group)
475    }
476
477    fn parse_unknown_section(
478        &mut self,
479        module: &mut crate::Module,
480        id: u8,
481        contents: &[u8],
482    ) -> Result<(), Error<Self::Error>> {
483        utils::parse_unknown_section(self, module, id, contents)
484    }
485
486    /// A hook method that is called inside [`Reencode::parse_core_module`]
487    /// before and after every non-custom core wasm section.
488    ///
489    /// This method can be used to insert new custom sections in between those
490    /// sections, or to detect when a non-custom section is missing and insert
491    /// it in the [proper order].
492    ///
493    /// The `after` parameter is `None` iff the hook is called before the first
494    /// non-custom section, and `Some(s)` afterwards, where `s` is the
495    /// [`SectionId`] of the previous non-custom section.
496    ///
497    /// The `before` parameter is `None` iff the hook is called after the last
498    /// non-custom section, and `Some(s)` beforehand, where `s` is the
499    /// [`SectionId`] of the following non-custom section.
500    ///
501    /// [proper order]: https://webassembly.github.io/spec/core/binary/modules.html#binary-module
502    /// [`SectionId`]: crate::SectionId
503    fn intersperse_section_hook(
504        &mut self,
505        module: &mut crate::Module,
506        after: Option<crate::SectionId>,
507        before: Option<crate::SectionId>,
508    ) -> Result<(), Error<Self::Error>> {
509        utils::intersperse_section_hook(self, module, after, before)
510    }
511
512    fn parse_core_module(
513        &mut self,
514        module: &mut crate::Module,
515        parser: wasmparser::Parser,
516        data: &[u8],
517    ) -> Result<(), Error<Self::Error>> {
518        utils::parse_core_module(self, module, parser, data)
519    }
520
521    fn custom_name_section(
522        &mut self,
523        section: wasmparser::NameSectionReader<'_>,
524    ) -> Result<crate::NameSection, Error<Self::Error>> {
525        utils::custom_name_section(self, section)
526    }
527
528    fn parse_custom_name_subsection(
529        &mut self,
530        names: &mut crate::NameSection,
531        section: wasmparser::Name<'_>,
532    ) -> Result<(), Error<Self::Error>> {
533        utils::parse_custom_name_subsection(self, names, section)
534    }
535
536    fn data_count(&mut self, count: u32) -> u32 {
537        count
538    }
539
540    fn start_section(&mut self, start: u32) -> u32 {
541        self.function_index(start)
542    }
543}
544
545/// An error when re-encoding from `wasmparser` to `wasm-encoder`.
546#[derive(Debug)]
547pub enum Error<E = Infallible> {
548    /// There was a type reference that was canonicalized and no longer
549    /// references an index into a module's types space, so we cannot encode it
550    /// into a Wasm binary again.
551    CanonicalizedHeapTypeReference,
552    /// The const expression is invalid: not actually constant or something like
553    /// that.
554    InvalidConstExpr,
555    /// The code section size listed was not valid for the wasm binary provided.
556    InvalidCodeSectionSize,
557    /// There was a section that does not belong into a core wasm module.
558    UnexpectedNonCoreModuleSection,
559    /// There was a section that does not belong into a component module.
560    UnexpectedNonComponentSection,
561    /// A core type definition was found in a component that's not supported.
562    UnsupportedCoreTypeInComponent,
563    /// There was an error when parsing.
564    ParseError(wasmparser::BinaryReaderError),
565    /// There was a user-defined error when re-encoding.
566    UserError(E),
567}
568
569impl<E> From<wasmparser::BinaryReaderError> for Error<E> {
570    fn from(err: wasmparser::BinaryReaderError) -> Self {
571        Self::ParseError(err)
572    }
573}
574
575impl<E: core::fmt::Display> core::fmt::Display for Error<E> {
576    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
577        match self {
578            Self::ParseError(_e) => {
579                write!(fmt, "There was an error when parsing")
580            }
581            Self::UserError(e) => write!(fmt, "{e}"),
582            Self::InvalidConstExpr => write!(fmt, "The const expression was invalid"),
583            Self::UnexpectedNonCoreModuleSection => write!(
584                fmt,
585                "There was a section that does not belong into a core wasm module"
586            ),
587            Self::UnexpectedNonComponentSection => write!(
588                fmt,
589                "There was a section that does not belong into a component"
590            ),
591            Self::CanonicalizedHeapTypeReference => write!(
592                fmt,
593                "There was a canonicalized heap type reference without type index information"
594            ),
595            Self::UnsupportedCoreTypeInComponent => {
596                fmt.write_str("unsupported core type in a component")
597            }
598            Self::InvalidCodeSectionSize => fmt.write_str("invalid code section size"),
599        }
600    }
601}
602
603#[cfg(any(feature = "std", core_error))]
604impl<E: 'static + StdError> StdError for Error<E> {
605    fn source(&self) -> Option<&(dyn StdError + 'static)> {
606        match self {
607            Self::ParseError(e) => Some(e),
608            Self::UserError(e) => Some(e),
609            Self::InvalidConstExpr
610            | Self::CanonicalizedHeapTypeReference
611            | Self::UnexpectedNonCoreModuleSection
612            | Self::UnexpectedNonComponentSection
613            | Self::UnsupportedCoreTypeInComponent
614            | Self::InvalidCodeSectionSize => None,
615        }
616    }
617}
618
619/// Reencodes `wasmparser` into `wasm-encoder` so that the encoded wasm is
620/// identical to the input and can be parsed and encoded again.
621#[derive(Debug)]
622pub struct RoundtripReencoder;
623
624impl Reencode for RoundtripReencoder {
625    type Error = Infallible;
626}
627
628#[allow(missing_docs)] // FIXME
629pub mod utils {
630    use super::{Error, Reencode};
631    use crate::{CoreTypeEncoder, Encode};
632    use alloc::vec::Vec;
633    use core::ops::Range;
634
635    pub fn parse_core_module<T: ?Sized + Reencode>(
636        reencoder: &mut T,
637        module: &mut crate::Module,
638        parser: wasmparser::Parser,
639        data: &[u8],
640    ) -> Result<(), Error<T::Error>> {
641        fn handle_intersperse_section_hook<T: ?Sized + Reencode>(
642            reencoder: &mut T,
643            module: &mut crate::Module,
644            last_section: &mut Option<crate::SectionId>,
645            next_section: Option<crate::SectionId>,
646        ) -> Result<(), Error<T::Error>> {
647            let after = core::mem::replace(last_section, next_section);
648            let before = next_section;
649            reencoder.intersperse_section_hook(module, after, before)
650        }
651
652        // Convert from `range` to a byte range within `data` while
653        // accounting for various offsets. Then create a
654        // `CodeSectionReader` (which notably the payload does not
655        // give us here) and recurse with that. This means that
656        // users overridding `parse_code_section` always get that
657        // function called.
658        let orig_offset = parser.offset() as usize;
659        let get_original_section = |range: Range<usize>| {
660            data.get(range.start - orig_offset..range.end - orig_offset)
661                .ok_or(Error::InvalidCodeSectionSize)
662        };
663        let mut last_section = None;
664
665        for section in parser.parse_all(data) {
666            match section? {
667                wasmparser::Payload::Version {
668                    encoding: wasmparser::Encoding::Module,
669                    ..
670                } => (),
671                wasmparser::Payload::Version { .. } => {
672                    return Err(Error::UnexpectedNonCoreModuleSection)
673                }
674                wasmparser::Payload::TypeSection(section) => {
675                    handle_intersperse_section_hook(
676                        reencoder,
677                        module,
678                        &mut last_section,
679                        Some(crate::SectionId::Type),
680                    )?;
681                    let mut types = crate::TypeSection::new();
682                    reencoder.parse_type_section(&mut types, section)?;
683                    module.section(&types);
684                }
685                wasmparser::Payload::ImportSection(section) => {
686                    handle_intersperse_section_hook(
687                        reencoder,
688                        module,
689                        &mut last_section,
690                        Some(crate::SectionId::Import),
691                    )?;
692                    let mut imports = crate::ImportSection::new();
693                    reencoder.parse_import_section(&mut imports, section)?;
694                    module.section(&imports);
695                }
696                wasmparser::Payload::FunctionSection(section) => {
697                    handle_intersperse_section_hook(
698                        reencoder,
699                        module,
700                        &mut last_section,
701                        Some(crate::SectionId::Function),
702                    )?;
703                    let mut functions = crate::FunctionSection::new();
704                    reencoder.parse_function_section(&mut functions, section)?;
705                    module.section(&functions);
706                }
707                wasmparser::Payload::TableSection(section) => {
708                    handle_intersperse_section_hook(
709                        reencoder,
710                        module,
711                        &mut last_section,
712                        Some(crate::SectionId::Table),
713                    )?;
714                    let mut tables = crate::TableSection::new();
715                    reencoder.parse_table_section(&mut tables, section)?;
716                    module.section(&tables);
717                }
718                wasmparser::Payload::MemorySection(section) => {
719                    handle_intersperse_section_hook(
720                        reencoder,
721                        module,
722                        &mut last_section,
723                        Some(crate::SectionId::Memory),
724                    )?;
725                    let mut memories = crate::MemorySection::new();
726                    reencoder.parse_memory_section(&mut memories, section)?;
727                    module.section(&memories);
728                }
729                wasmparser::Payload::TagSection(section) => {
730                    handle_intersperse_section_hook(
731                        reencoder,
732                        module,
733                        &mut last_section,
734                        Some(crate::SectionId::Tag),
735                    )?;
736                    let mut tags = crate::TagSection::new();
737                    reencoder.parse_tag_section(&mut tags, section)?;
738                    module.section(&tags);
739                }
740                wasmparser::Payload::GlobalSection(section) => {
741                    handle_intersperse_section_hook(
742                        reencoder,
743                        module,
744                        &mut last_section,
745                        Some(crate::SectionId::Global),
746                    )?;
747                    let mut globals = crate::GlobalSection::new();
748                    reencoder.parse_global_section(&mut globals, section)?;
749                    module.section(&globals);
750                }
751                wasmparser::Payload::ExportSection(section) => {
752                    handle_intersperse_section_hook(
753                        reencoder,
754                        module,
755                        &mut last_section,
756                        Some(crate::SectionId::Export),
757                    )?;
758                    let mut exports = crate::ExportSection::new();
759                    reencoder.parse_export_section(&mut exports, section)?;
760                    module.section(&exports);
761                }
762                wasmparser::Payload::StartSection { func, .. } => {
763                    handle_intersperse_section_hook(
764                        reencoder,
765                        module,
766                        &mut last_section,
767                        Some(crate::SectionId::Start),
768                    )?;
769                    module.section(&crate::StartSection {
770                        function_index: reencoder.start_section(func),
771                    });
772                }
773                wasmparser::Payload::ElementSection(section) => {
774                    handle_intersperse_section_hook(
775                        reencoder,
776                        module,
777                        &mut last_section,
778                        Some(crate::SectionId::Element),
779                    )?;
780                    let mut elements = crate::ElementSection::new();
781                    reencoder.parse_element_section(&mut elements, section)?;
782                    module.section(&elements);
783                }
784                wasmparser::Payload::DataCountSection { count, .. } => {
785                    handle_intersperse_section_hook(
786                        reencoder,
787                        module,
788                        &mut last_section,
789                        Some(crate::SectionId::DataCount),
790                    )?;
791                    let count = reencoder.data_count(count);
792                    module.section(&crate::DataCountSection { count });
793                }
794                wasmparser::Payload::DataSection(section) => {
795                    handle_intersperse_section_hook(
796                        reencoder,
797                        module,
798                        &mut last_section,
799                        Some(crate::SectionId::Data),
800                    )?;
801                    let mut data = crate::DataSection::new();
802                    reencoder.parse_data_section(&mut data, section)?;
803                    module.section(&data);
804                }
805                wasmparser::Payload::CodeSectionStart { range, .. } => {
806                    handle_intersperse_section_hook(
807                        reencoder,
808                        module,
809                        &mut last_section,
810                        Some(crate::SectionId::Code),
811                    )?;
812                    let mut codes = crate::CodeSection::new();
813
814                    // Convert from `range` to a byte range within `data` while
815                    // accounting for various offsets. Then create a
816                    // `CodeSectionReader` (which notably the payload does not
817                    // give us here) and recurse with that. This means that
818                    // users overridding `parse_code_section` always get that
819                    // function called.
820                    let section = get_original_section(range.clone())?;
821                    let reader = wasmparser::BinaryReader::new(section, range.start);
822                    let section = wasmparser::CodeSectionReader::new(reader)?;
823                    reencoder.parse_code_section(&mut codes, section)?;
824                    module.section(&codes);
825                }
826
827                // Parsing of code section entries (function bodies) happens
828                // above during the handling of the code section. That means
829                // that we just skip all these payloads.
830                wasmparser::Payload::CodeSectionEntry(_) => {}
831
832                #[cfg(feature = "component-model")]
833                wasmparser::Payload::ModuleSection { .. }
834                | wasmparser::Payload::InstanceSection(_)
835                | wasmparser::Payload::CoreTypeSection(_)
836                | wasmparser::Payload::ComponentSection { .. }
837                | wasmparser::Payload::ComponentInstanceSection(_)
838                | wasmparser::Payload::ComponentAliasSection(_)
839                | wasmparser::Payload::ComponentTypeSection(_)
840                | wasmparser::Payload::ComponentCanonicalSection(_)
841                | wasmparser::Payload::ComponentStartSection { .. }
842                | wasmparser::Payload::ComponentImportSection(_)
843                | wasmparser::Payload::ComponentExportSection(_) => {
844                    return Err(Error::UnexpectedNonCoreModuleSection)
845                }
846                wasmparser::Payload::CustomSection(section) => {
847                    reencoder.parse_custom_section(module, section)?;
848                }
849                wasmparser::Payload::End(_) => {
850                    handle_intersperse_section_hook(reencoder, module, &mut last_section, None)?;
851                }
852
853                other => match other.as_section() {
854                    Some((id, range)) => {
855                        let section = get_original_section(range)?;
856                        reencoder.parse_unknown_section(module, id, section)?;
857                    }
858                    None => unreachable!(),
859                },
860            }
861        }
862
863        Ok(())
864    }
865
866    /// A hook method that is called inside [`Reencode::parse_core_module`]
867    /// before and after every non-custom core wasm section.
868    ///
869    /// This method can be used to insert new custom sections in between those
870    /// sections, or to detect when a non-custom section is missing and insert
871    /// it in the [proper order].
872    ///
873    /// The `after` parameter is `None` iff the hook is called before the first
874    /// non-custom section, and `Some(s)` afterwards, where `s` is the
875    /// [`SectionId`] of the previous non-custom section.
876    ///
877    /// The `before` parameter is `None` iff the hook is called after the last
878    /// non-custom section, and `Some(s)` beforehand, where `s` is the
879    /// [`SectionId`] of the following non-custom section.
880    ///
881    /// [proper order]: https://webassembly.github.io/spec/core/binary/modules.html#binary-module
882    /// [`SectionId`]: crate::SectionId
883    pub fn intersperse_section_hook<T: ?Sized + Reencode>(
884        _reencoder: &mut T,
885        _module: &mut crate::Module,
886        _after: Option<crate::SectionId>,
887        _before: Option<crate::SectionId>,
888    ) -> Result<(), Error<T::Error>> {
889        Ok(())
890    }
891
892    pub fn memory_index<T: ?Sized + Reencode>(_reencoder: &mut T, memory: u32) -> u32 {
893        memory
894    }
895
896    pub fn ieee32_arg<T: ?Sized + Reencode>(
897        _reencoder: &mut T,
898        arg: wasmparser::Ieee32,
899    ) -> crate::Ieee32 {
900        crate::Ieee32(arg.bits())
901    }
902
903    pub fn ieee64_arg<T: ?Sized + Reencode>(
904        _reencoder: &mut T,
905        arg: wasmparser::Ieee64,
906    ) -> crate::Ieee64 {
907        crate::Ieee64(arg.bits())
908    }
909
910    pub fn mem_arg<T: ?Sized + Reencode>(
911        reencoder: &mut T,
912        arg: wasmparser::MemArg,
913    ) -> crate::MemArg {
914        crate::MemArg {
915            offset: arg.offset,
916            align: arg.align.into(),
917            memory_index: reencoder.memory_index(arg.memory),
918        }
919    }
920
921    pub fn ordering<T: ?Sized + Reencode>(
922        _reencoder: &mut T,
923        arg: wasmparser::Ordering,
924    ) -> crate::Ordering {
925        match arg {
926            wasmparser::Ordering::SeqCst => crate::Ordering::SeqCst,
927            wasmparser::Ordering::AcqRel => crate::Ordering::AcqRel,
928        }
929    }
930
931    pub fn function_index<T: ?Sized + Reencode>(_reencoder: &mut T, func: u32) -> u32 {
932        func
933    }
934
935    pub fn tag_index<T: ?Sized + Reencode>(_reencoder: &mut T, tag: u32) -> u32 {
936        tag
937    }
938
939    pub fn catch<T: ?Sized + Reencode>(reencoder: &mut T, arg: wasmparser::Catch) -> crate::Catch {
940        match arg {
941            wasmparser::Catch::One { tag, label } => crate::Catch::One {
942                tag: reencoder.tag_index(tag),
943                label,
944            },
945            wasmparser::Catch::OneRef { tag, label } => crate::Catch::OneRef {
946                tag: reencoder.tag_index(tag),
947                label,
948            },
949            wasmparser::Catch::All { label } => crate::Catch::All { label },
950            wasmparser::Catch::AllRef { label } => crate::Catch::AllRef { label },
951        }
952    }
953
954    pub fn handle<T: ?Sized + Reencode>(
955        reencoder: &mut T,
956        arg: wasmparser::Handle,
957    ) -> crate::Handle {
958        match arg {
959            wasmparser::Handle::OnLabel { tag, label } => crate::Handle::OnLabel {
960                tag: reencoder.tag_index(tag),
961                label,
962            },
963            wasmparser::Handle::OnSwitch { tag } => crate::Handle::OnSwitch {
964                tag: reencoder.tag_index(tag),
965            },
966        }
967    }
968
969    /// Parses the input `section` given from the `wasmparser` crate and
970    /// adds the custom section to the `module`.
971    pub fn parse_custom_section<T: ?Sized + Reencode>(
972        reencoder: &mut T,
973        module: &mut crate::Module,
974        section: wasmparser::CustomSectionReader<'_>,
975    ) -> Result<(), Error<T::Error>> {
976        match section.as_known() {
977            wasmparser::KnownCustom::Name(name) => {
978                module.section(&reencoder.custom_name_section(name)?);
979            }
980            _ => {
981                module.section(&reencoder.custom_section(section));
982            }
983        }
984        Ok(())
985    }
986
987    /// Converts the input `section` given from the `wasmparser` crate into an
988    /// encoded custom section.
989    pub fn custom_section<'a, T: ?Sized + Reencode>(
990        _reencoder: &mut T,
991        section: wasmparser::CustomSectionReader<'a>,
992    ) -> crate::CustomSection<'a> {
993        crate::CustomSection {
994            data: section.data().into(),
995            name: section.name().into(),
996        }
997    }
998
999    pub fn export_kind<T: ?Sized + Reencode>(
1000        _reencoder: &mut T,
1001        external_kind: wasmparser::ExternalKind,
1002    ) -> crate::ExportKind {
1003        match external_kind {
1004            wasmparser::ExternalKind::Func => crate::ExportKind::Func,
1005            wasmparser::ExternalKind::Table => crate::ExportKind::Table,
1006            wasmparser::ExternalKind::Memory => crate::ExportKind::Memory,
1007            wasmparser::ExternalKind::Global => crate::ExportKind::Global,
1008            wasmparser::ExternalKind::Tag => crate::ExportKind::Tag,
1009        }
1010    }
1011
1012    pub fn memory_type<T: ?Sized + Reencode>(
1013        _reencoder: &mut T,
1014        memory_ty: wasmparser::MemoryType,
1015    ) -> crate::MemoryType {
1016        crate::MemoryType {
1017            minimum: memory_ty.initial,
1018            maximum: memory_ty.maximum,
1019            memory64: memory_ty.memory64,
1020            shared: memory_ty.shared,
1021            page_size_log2: memory_ty.page_size_log2,
1022        }
1023    }
1024
1025    pub fn tag_kind<T: ?Sized + Reencode>(
1026        _reencoder: &mut T,
1027        kind: wasmparser::TagKind,
1028    ) -> crate::TagKind {
1029        match kind {
1030            wasmparser::TagKind::Exception => crate::TagKind::Exception,
1031        }
1032    }
1033
1034    pub fn type_index<T: ?Sized + Reencode>(_reencoder: &mut T, ty: u32) -> u32 {
1035        ty
1036    }
1037
1038    pub fn type_index_unpacked<T: ?Sized + Reencode>(
1039        reencoder: &mut T,
1040        ty: wasmparser::UnpackedIndex,
1041    ) -> Result<u32, Error<T::Error>> {
1042        ty.as_module_index()
1043            .map(|ty| reencoder.type_index(ty))
1044            .ok_or(Error::CanonicalizedHeapTypeReference)
1045    }
1046
1047    pub fn tag_type<T: ?Sized + Reencode>(
1048        reencoder: &mut T,
1049        tag_ty: wasmparser::TagType,
1050    ) -> crate::TagType {
1051        crate::TagType {
1052            kind: reencoder.tag_kind(tag_ty.kind),
1053            func_type_idx: reencoder.type_index(tag_ty.func_type_idx),
1054        }
1055    }
1056
1057    pub fn abstract_heap_type<T: ?Sized + Reencode>(
1058        _reencoder: &mut T,
1059        value: wasmparser::AbstractHeapType,
1060    ) -> crate::AbstractHeapType {
1061        use wasmparser::AbstractHeapType::*;
1062        match value {
1063            Func => crate::AbstractHeapType::Func,
1064            Extern => crate::AbstractHeapType::Extern,
1065            Any => crate::AbstractHeapType::Any,
1066            None => crate::AbstractHeapType::None,
1067            NoExtern => crate::AbstractHeapType::NoExtern,
1068            NoFunc => crate::AbstractHeapType::NoFunc,
1069            Eq => crate::AbstractHeapType::Eq,
1070            Struct => crate::AbstractHeapType::Struct,
1071            Array => crate::AbstractHeapType::Array,
1072            I31 => crate::AbstractHeapType::I31,
1073            Exn => crate::AbstractHeapType::Exn,
1074            NoExn => crate::AbstractHeapType::NoExn,
1075            Cont => crate::AbstractHeapType::Cont,
1076            NoCont => crate::AbstractHeapType::NoCont,
1077        }
1078    }
1079
1080    /// Parses the input `section` given from the `wasmparser` crate and adds
1081    /// all the types to the `types` section.
1082    pub fn parse_type_section<T: ?Sized + Reencode>(
1083        reencoder: &mut T,
1084        types: &mut crate::TypeSection,
1085        section: wasmparser::TypeSectionReader<'_>,
1086    ) -> Result<(), Error<T::Error>> {
1087        for rec_group in section {
1088            reencoder.parse_recursive_type_group(types.ty(), rec_group?)?;
1089        }
1090        Ok(())
1091    }
1092
1093    /// Parses a single [`wasmparser::RecGroup`] and adds it to the `types` section.
1094    pub fn parse_recursive_type_group<T: ?Sized + Reencode>(
1095        reencoder: &mut T,
1096        encoder: CoreTypeEncoder,
1097        rec_group: wasmparser::RecGroup,
1098    ) -> Result<(), Error<T::Error>> {
1099        if rec_group.is_explicit_rec_group() {
1100            let subtypes = rec_group
1101                .into_types()
1102                .map(|t| reencoder.sub_type(t))
1103                .collect::<Result<Vec<_>, _>>()?;
1104            encoder.rec(subtypes);
1105        } else {
1106            let ty = rec_group.into_types().next().unwrap();
1107            encoder.subtype(&reencoder.sub_type(ty)?);
1108        }
1109        Ok(())
1110    }
1111
1112    pub fn sub_type<T: ?Sized + Reencode>(
1113        reencoder: &mut T,
1114        sub_ty: wasmparser::SubType,
1115    ) -> Result<crate::SubType, Error<T::Error>> {
1116        Ok(crate::SubType {
1117            is_final: sub_ty.is_final,
1118            supertype_idx: sub_ty
1119                .supertype_idx
1120                .map(|i| reencoder.type_index_unpacked(i.unpack()))
1121                .transpose()?,
1122            composite_type: reencoder.composite_type(sub_ty.composite_type)?,
1123        })
1124    }
1125
1126    pub fn composite_type<T: ?Sized + Reencode>(
1127        reencoder: &mut T,
1128        composite_ty: wasmparser::CompositeType,
1129    ) -> Result<crate::CompositeType, Error<T::Error>> {
1130        let inner = match composite_ty.inner {
1131            wasmparser::CompositeInnerType::Func(f) => {
1132                crate::CompositeInnerType::Func(reencoder.func_type(f)?)
1133            }
1134            wasmparser::CompositeInnerType::Array(a) => {
1135                crate::CompositeInnerType::Array(reencoder.array_type(a)?)
1136            }
1137            wasmparser::CompositeInnerType::Struct(s) => {
1138                crate::CompositeInnerType::Struct(reencoder.struct_type(s)?)
1139            }
1140            wasmparser::CompositeInnerType::Cont(c) => {
1141                crate::CompositeInnerType::Cont(reencoder.cont_type(c)?)
1142            }
1143        };
1144        Ok(crate::CompositeType {
1145            inner,
1146            shared: composite_ty.shared,
1147        })
1148    }
1149
1150    pub fn func_type<T: ?Sized + Reencode>(
1151        reencoder: &mut T,
1152        func_ty: wasmparser::FuncType,
1153    ) -> Result<crate::FuncType, Error<T::Error>> {
1154        let mut buf = Vec::with_capacity(func_ty.params().len() + func_ty.results().len());
1155        for ty in func_ty.params().iter().chain(func_ty.results()).copied() {
1156            buf.push(reencoder.val_type(ty)?);
1157        }
1158        Ok(crate::FuncType::from_parts(
1159            buf.into(),
1160            func_ty.params().len(),
1161        ))
1162    }
1163
1164    pub fn array_type<T: ?Sized + Reencode>(
1165        reencoder: &mut T,
1166        array_ty: wasmparser::ArrayType,
1167    ) -> Result<crate::ArrayType, Error<T::Error>> {
1168        Ok(crate::ArrayType(reencoder.field_type(array_ty.0)?))
1169    }
1170
1171    pub fn struct_type<T: ?Sized + Reencode>(
1172        reencoder: &mut T,
1173        struct_ty: wasmparser::StructType,
1174    ) -> Result<crate::StructType, Error<T::Error>> {
1175        Ok(crate::StructType {
1176            fields: struct_ty
1177                .fields
1178                .iter()
1179                .map(|field_ty| reencoder.field_type(*field_ty))
1180                .collect::<Result<_, _>>()?,
1181        })
1182    }
1183
1184    pub fn field_type<T: ?Sized + Reencode>(
1185        reencoder: &mut T,
1186        field_ty: wasmparser::FieldType,
1187    ) -> Result<crate::FieldType, Error<T::Error>> {
1188        Ok(crate::FieldType {
1189            element_type: reencoder.storage_type(field_ty.element_type)?,
1190            mutable: field_ty.mutable,
1191        })
1192    }
1193
1194    pub fn storage_type<T: ?Sized + Reencode>(
1195        reencoder: &mut T,
1196        storage_ty: wasmparser::StorageType,
1197    ) -> Result<crate::StorageType, Error<T::Error>> {
1198        Ok(match storage_ty {
1199            wasmparser::StorageType::I8 => crate::StorageType::I8,
1200            wasmparser::StorageType::I16 => crate::StorageType::I16,
1201            wasmparser::StorageType::Val(v) => crate::StorageType::Val(reencoder.val_type(v)?),
1202        })
1203    }
1204
1205    pub fn cont_type<T: ?Sized + Reencode>(
1206        reencoder: &mut T,
1207        cont_ty: wasmparser::ContType,
1208    ) -> Result<crate::ContType, Error<T::Error>> {
1209        Ok(crate::ContType(
1210            reencoder.type_index_unpacked(cont_ty.0.unpack())?,
1211        ))
1212    }
1213
1214    pub fn val_type<T: ?Sized + Reencode>(
1215        reencoder: &mut T,
1216        val_ty: wasmparser::ValType,
1217    ) -> Result<crate::ValType, Error<T::Error>> {
1218        Ok(match val_ty {
1219            wasmparser::ValType::I32 => crate::ValType::I32,
1220            wasmparser::ValType::I64 => crate::ValType::I64,
1221            wasmparser::ValType::F32 => crate::ValType::F32,
1222            wasmparser::ValType::F64 => crate::ValType::F64,
1223            wasmparser::ValType::V128 => crate::ValType::V128,
1224            wasmparser::ValType::Ref(r) => crate::ValType::Ref(reencoder.ref_type(r)?),
1225        })
1226    }
1227
1228    pub fn ref_type<T: ?Sized + Reencode>(
1229        reencoder: &mut T,
1230        ref_type: wasmparser::RefType,
1231    ) -> Result<crate::RefType, Error<T::Error>> {
1232        Ok(crate::RefType {
1233            nullable: ref_type.is_nullable(),
1234            heap_type: reencoder.heap_type(ref_type.heap_type())?,
1235        })
1236    }
1237
1238    pub fn heap_type<T: ?Sized + Reencode>(
1239        reencoder: &mut T,
1240        heap_type: wasmparser::HeapType,
1241    ) -> Result<crate::HeapType, Error<T::Error>> {
1242        Ok(match heap_type {
1243            wasmparser::HeapType::Concrete(i) => {
1244                crate::HeapType::Concrete(reencoder.type_index_unpacked(i)?)
1245            }
1246            wasmparser::HeapType::Abstract { shared, ty } => crate::HeapType::Abstract {
1247                shared,
1248                ty: reencoder.abstract_heap_type(ty),
1249            },
1250        })
1251    }
1252
1253    /// Parses the input `section` given from the `wasmparser` crate and adds
1254    /// all the tables to the `tables` section.
1255    pub fn parse_table_section<T: ?Sized + Reencode>(
1256        reencoder: &mut T,
1257        tables: &mut crate::TableSection,
1258        section: wasmparser::TableSectionReader<'_>,
1259    ) -> Result<(), Error<T::Error>> {
1260        for table in section {
1261            reencoder.parse_table(tables, table?)?;
1262        }
1263        Ok(())
1264    }
1265
1266    /// Parses a single [`wasmparser::Table`] and adds it to the `tables` section.
1267    pub fn parse_table<T: ?Sized + Reencode>(
1268        reencoder: &mut T,
1269        tables: &mut crate::TableSection,
1270        table: wasmparser::Table<'_>,
1271    ) -> Result<(), Error<T::Error>> {
1272        let ty = reencoder.table_type(table.ty)?;
1273        match table.init {
1274            wasmparser::TableInit::RefNull => {
1275                tables.table(ty);
1276            }
1277            wasmparser::TableInit::Expr(e) => {
1278                tables.table_with_init(ty, &reencoder.const_expr(e)?);
1279            }
1280        }
1281        Ok(())
1282    }
1283
1284    pub fn table_type<T: ?Sized + Reencode>(
1285        reencoder: &mut T,
1286        table_ty: wasmparser::TableType,
1287    ) -> Result<crate::TableType, Error<T::Error>> {
1288        Ok(crate::TableType {
1289            element_type: reencoder.ref_type(table_ty.element_type)?,
1290            minimum: table_ty.initial,
1291            maximum: table_ty.maximum,
1292            table64: table_ty.table64,
1293            shared: table_ty.shared,
1294        })
1295    }
1296
1297    /// Parses the input `section` given from the `wasmparser` crate and adds
1298    /// all the tags to the `tags` section.
1299    pub fn parse_tag_section<T: ?Sized + Reencode>(
1300        reencoder: &mut T,
1301        tags: &mut crate::TagSection,
1302        section: wasmparser::TagSectionReader<'_>,
1303    ) -> Result<(), Error<T::Error>> {
1304        for tag in section {
1305            let tag = tag?;
1306            tags.tag(reencoder.tag_type(tag));
1307        }
1308        Ok(())
1309    }
1310
1311    /// Parses the input `section` given from the `wasmparser` crate and adds
1312    /// all the exports to the `exports` section.
1313    pub fn parse_export_section<T: ?Sized + Reencode>(
1314        reencoder: &mut T,
1315        exports: &mut crate::ExportSection,
1316        section: wasmparser::ExportSectionReader<'_>,
1317    ) -> Result<(), Error<T::Error>> {
1318        for export in section {
1319            reencoder.parse_export(exports, export?);
1320        }
1321        Ok(())
1322    }
1323
1324    /// Parses the single [`wasmparser::Export`] provided and adds it to the
1325    /// `exports` section.
1326    pub fn parse_export<T: ?Sized + Reencode>(
1327        reencoder: &mut T,
1328        exports: &mut crate::ExportSection,
1329        export: wasmparser::Export<'_>,
1330    ) {
1331        exports.export(
1332            export.name,
1333            reencoder.export_kind(export.kind),
1334            reencoder.external_index(export.kind, export.index),
1335        );
1336    }
1337
1338    /// Parses the input `section` given from the `wasmparser` crate and adds
1339    /// all the globals to the `globals` section.
1340    pub fn parse_global_section<T: ?Sized + Reencode>(
1341        reencoder: &mut T,
1342        globals: &mut crate::GlobalSection,
1343        section: wasmparser::GlobalSectionReader<'_>,
1344    ) -> Result<(), Error<T::Error>> {
1345        for global in section {
1346            reencoder.parse_global(globals, global?)?;
1347        }
1348        Ok(())
1349    }
1350
1351    /// Parses the single [`wasmparser::Global`] provided and adds it to the
1352    /// `globals` section.
1353    pub fn parse_global<T: ?Sized + Reencode>(
1354        reencoder: &mut T,
1355        globals: &mut crate::GlobalSection,
1356        global: wasmparser::Global<'_>,
1357    ) -> Result<(), Error<T::Error>> {
1358        globals.global(
1359            reencoder.global_type(global.ty)?,
1360            &reencoder.const_expr(global.init_expr)?,
1361        );
1362        Ok(())
1363    }
1364
1365    pub fn global_type<T: ?Sized + Reencode>(
1366        reencoder: &mut T,
1367        global_ty: wasmparser::GlobalType,
1368    ) -> Result<crate::GlobalType, Error<T::Error>> {
1369        Ok(crate::GlobalType {
1370            val_type: reencoder.val_type(global_ty.content_type)?,
1371            mutable: global_ty.mutable,
1372            shared: global_ty.shared,
1373        })
1374    }
1375
1376    pub fn entity_type<T: ?Sized + Reencode>(
1377        reencoder: &mut T,
1378        type_ref: wasmparser::TypeRef,
1379    ) -> Result<crate::EntityType, Error<T::Error>> {
1380        Ok(match type_ref {
1381            wasmparser::TypeRef::Func(i) => crate::EntityType::Function(reencoder.type_index(i)),
1382            wasmparser::TypeRef::Table(t) => crate::EntityType::Table(reencoder.table_type(t)?),
1383            wasmparser::TypeRef::Memory(m) => crate::EntityType::Memory(reencoder.memory_type(m)),
1384            wasmparser::TypeRef::Global(g) => crate::EntityType::Global(reencoder.global_type(g)?),
1385            wasmparser::TypeRef::Tag(t) => crate::EntityType::Tag(reencoder.tag_type(t)),
1386        })
1387    }
1388
1389    /// Parses the input `section` given from the `wasmparser` crate and adds
1390    /// all the imports to the `import` section.
1391    pub fn parse_import_section<T: ?Sized + Reencode>(
1392        reencoder: &mut T,
1393        imports: &mut crate::ImportSection,
1394        section: wasmparser::ImportSectionReader<'_>,
1395    ) -> Result<(), Error<T::Error>> {
1396        for import in section {
1397            reencoder.parse_import(imports, import?)?;
1398        }
1399        Ok(())
1400    }
1401
1402    /// Parses the single [`wasmparser::Import`] provided and adds it to the
1403    /// `import` section.
1404    pub fn parse_import<T: ?Sized + Reencode>(
1405        reencoder: &mut T,
1406        imports: &mut crate::ImportSection,
1407        import: wasmparser::Import<'_>,
1408    ) -> Result<(), Error<T::Error>> {
1409        imports.import(
1410            import.module,
1411            import.name,
1412            reencoder.entity_type(import.ty)?,
1413        );
1414        Ok(())
1415    }
1416
1417    /// Parses the input `section` given from the `wasmparser` crate and adds
1418    /// all the memories to the `memories` section.
1419    pub fn parse_memory_section<T: ?Sized + Reencode>(
1420        reencoder: &mut T,
1421        memories: &mut crate::MemorySection,
1422        section: wasmparser::MemorySectionReader<'_>,
1423    ) -> Result<(), Error<T::Error>> {
1424        for memory in section {
1425            let memory = memory?;
1426            memories.memory(reencoder.memory_type(memory));
1427        }
1428        Ok(())
1429    }
1430
1431    /// Parses the input `section` given from the `wasmparser` crate and adds
1432    /// all the functions to the `functions` section.
1433    pub fn parse_function_section<T: ?Sized + Reencode>(
1434        reencoder: &mut T,
1435        functions: &mut crate::FunctionSection,
1436        section: wasmparser::FunctionSectionReader<'_>,
1437    ) -> Result<(), Error<T::Error>> {
1438        for func in section {
1439            functions.function(reencoder.type_index(func?));
1440        }
1441        Ok(())
1442    }
1443
1444    /// Parses the input `section` given from the `wasmparser` crate and adds
1445    /// all the data to the `data` section.
1446    pub fn parse_data_section<T: ?Sized + Reencode>(
1447        reencoder: &mut T,
1448        data: &mut crate::DataSection,
1449        section: wasmparser::DataSectionReader<'_>,
1450    ) -> Result<(), Error<T::Error>> {
1451        for datum in section {
1452            reencoder.parse_data(data, datum?)?;
1453        }
1454        Ok(())
1455    }
1456
1457    /// Parses a single [`wasmparser::Data`] and adds it to the `data` section.
1458    pub fn parse_data<T: ?Sized + Reencode>(
1459        reencoder: &mut T,
1460        data: &mut crate::DataSection,
1461        datum: wasmparser::Data<'_>,
1462    ) -> Result<(), Error<T::Error>> {
1463        match datum.kind {
1464            wasmparser::DataKind::Active {
1465                memory_index,
1466                offset_expr,
1467            } => data.active(
1468                reencoder.memory_index(memory_index),
1469                &reencoder.const_expr(offset_expr)?,
1470                datum.data.iter().copied(),
1471            ),
1472            wasmparser::DataKind::Passive => data.passive(datum.data.iter().copied()),
1473        };
1474        Ok(())
1475    }
1476
1477    /// Parses the input `section` given from the `wasmparser` crate and adds
1478    /// all the elements to the `element` section.
1479    pub fn parse_element_section<T: ?Sized + Reencode>(
1480        reencoder: &mut T,
1481        elements: &mut crate::ElementSection,
1482        section: wasmparser::ElementSectionReader<'_>,
1483    ) -> Result<(), Error<T::Error>> {
1484        for element in section {
1485            reencoder.parse_element(elements, element?)?;
1486        }
1487        Ok(())
1488    }
1489
1490    /// Parses the single [`wasmparser::Element`] provided and adds it to the
1491    /// `element` section.
1492    pub fn parse_element<T: ?Sized + Reencode>(
1493        reencoder: &mut T,
1494        elements: &mut crate::ElementSection,
1495        element: wasmparser::Element<'_>,
1496    ) -> Result<(), Error<T::Error>> {
1497        let elems = reencoder.element_items(element.items)?;
1498        match element.kind {
1499            wasmparser::ElementKind::Active {
1500                table_index,
1501                offset_expr,
1502            } => elements.active(
1503                // Inform the reencoder that a table index is being used even if
1504                // it's not actually present here. That helps wasm-mutate for
1505                // example which wants to track uses to know when it's ok to
1506                // remove a table.
1507                //
1508                // If the table index started at `None` and is still zero then
1509                // preserve this encoding and keep it at `None`. Otherwise if
1510                // the result is nonzero or it was previously nonzero then keep
1511                // that encoding too.
1512                match (table_index, reencoder.table_index(table_index.unwrap_or(0))) {
1513                    (None, 0) => None,
1514                    (_, n) => Some(n),
1515                },
1516                &reencoder.const_expr(offset_expr)?,
1517                elems,
1518            ),
1519            wasmparser::ElementKind::Passive => elements.passive(elems),
1520            wasmparser::ElementKind::Declared => elements.declared(elems),
1521        };
1522        Ok(())
1523    }
1524
1525    pub fn element_items<'a, T: ?Sized + Reencode>(
1526        reencoder: &mut T,
1527        items: wasmparser::ElementItems<'a>,
1528    ) -> Result<crate::Elements<'a>, Error<T::Error>> {
1529        Ok(match items {
1530            wasmparser::ElementItems::Functions(f) => {
1531                let mut funcs = Vec::new();
1532                for func in f {
1533                    funcs.push(reencoder.function_index(func?));
1534                }
1535                crate::Elements::Functions(funcs.into())
1536            }
1537            wasmparser::ElementItems::Expressions(ty, e) => {
1538                let mut exprs = Vec::new();
1539                for expr in e {
1540                    exprs.push(reencoder.const_expr(expr?)?);
1541                }
1542                crate::Elements::Expressions(reencoder.ref_type(ty)?, exprs.into())
1543            }
1544        })
1545    }
1546
1547    pub fn table_index<T: ?Sized + Reencode>(_reencoder: &mut T, table: u32) -> u32 {
1548        table
1549    }
1550
1551    pub fn global_index<T: ?Sized + Reencode>(_reencoder: &mut T, global: u32) -> u32 {
1552        global
1553    }
1554
1555    pub fn data_index<T: ?Sized + Reencode>(_reencoder: &mut T, data: u32) -> u32 {
1556        data
1557    }
1558
1559    pub fn element_index<T: ?Sized + Reencode>(_reencoder: &mut T, element: u32) -> u32 {
1560        element
1561    }
1562
1563    pub fn const_expr<T: ?Sized + Reencode>(
1564        reencoder: &mut T,
1565        const_expr: wasmparser::ConstExpr,
1566    ) -> Result<crate::ConstExpr, Error<T::Error>> {
1567        let mut ops = const_expr.get_operators_reader();
1568        let mut bytes = Vec::new();
1569
1570        while !ops.is_end_then_eof() {
1571            let insn = reencoder.parse_instruction(&mut ops)?;
1572            insn.encode(&mut bytes);
1573        }
1574
1575        Ok(crate::ConstExpr::raw(bytes))
1576    }
1577
1578    pub fn block_type<T: ?Sized + Reencode>(
1579        reencoder: &mut T,
1580        arg: wasmparser::BlockType,
1581    ) -> Result<crate::BlockType, Error<T::Error>> {
1582        match arg {
1583            wasmparser::BlockType::Empty => Ok(crate::BlockType::Empty),
1584            wasmparser::BlockType::FuncType(n) => {
1585                Ok(crate::BlockType::FunctionType(reencoder.type_index(n)))
1586            }
1587            wasmparser::BlockType::Type(t) => Ok(crate::BlockType::Result(reencoder.val_type(t)?)),
1588        }
1589    }
1590
1591    pub fn instruction<'a, T: ?Sized + Reencode>(
1592        reencoder: &mut T,
1593        arg: wasmparser::Operator<'a>,
1594    ) -> Result<crate::Instruction<'a>, Error<T::Error>> {
1595        use crate::Instruction;
1596        use alloc::borrow::Cow;
1597
1598        macro_rules! translate {
1599            ($( @$proposal:ident $op:ident $({ $($arg:ident: $argty:ty),* })? => $visit:ident ($($ann:tt)*))*) => {
1600                Ok(match arg {
1601                    $(
1602                        wasmparser::Operator::$op $({ $($arg),* })? => {
1603                            $(
1604                                $(let $arg = translate!(map $arg $arg);)*
1605                            )?
1606                            translate!(build $op $($($arg)*)?)
1607                        }
1608                    )*
1609                    unexpected => unreachable!("encountered unexpected Wasm operator: {unexpected:?}"),
1610                })
1611            };
1612
1613            // This case is used to map, based on the name of the field, from the
1614            // wasmparser payload type to the wasm-encoder payload type through
1615            // `Translator` as applicable.
1616            (map $arg:ident tag_index) => (reencoder.tag_index($arg));
1617            (map $arg:ident function_index) => (reencoder.function_index($arg));
1618            (map $arg:ident table) => (reencoder.table_index($arg));
1619            (map $arg:ident table_index) => (reencoder.table_index($arg));
1620            (map $arg:ident dst_table) => (reencoder.table_index($arg));
1621            (map $arg:ident src_table) => (reencoder.table_index($arg));
1622            (map $arg:ident type_index) => (reencoder.type_index($arg));
1623            (map $arg:ident array_type_index) => (reencoder.type_index($arg));
1624            (map $arg:ident array_type_index_dst) => (reencoder.type_index($arg));
1625            (map $arg:ident array_type_index_src) => (reencoder.type_index($arg));
1626            (map $arg:ident struct_type_index) => (reencoder.type_index($arg));
1627            (map $arg:ident global_index) => (reencoder.global_index($arg));
1628            (map $arg:ident mem) => (reencoder.memory_index($arg));
1629            (map $arg:ident src_mem) => (reencoder.memory_index($arg));
1630            (map $arg:ident dst_mem) => (reencoder.memory_index($arg));
1631            (map $arg:ident data_index) => (reencoder.data_index($arg));
1632            (map $arg:ident elem_index) => (reencoder.element_index($arg));
1633            (map $arg:ident array_data_index) => (reencoder.data_index($arg));
1634            (map $arg:ident array_elem_index) => (reencoder.element_index($arg));
1635            (map $arg:ident blockty) => (reencoder.block_type($arg)?);
1636            (map $arg:ident relative_depth) => ($arg);
1637            (map $arg:ident targets) => ((
1638                $arg
1639                    .targets()
1640                    .collect::<Result<Vec<_>, wasmparser::BinaryReaderError>>()?
1641                    .into(),
1642                $arg.default(),
1643            ));
1644            (map $arg:ident ty) => (reencoder.val_type($arg)?);
1645            (map $arg:ident tys) => (reencoder.val_types($arg)?);
1646            (map $arg:ident hty) => (reencoder.heap_type($arg)?);
1647            (map $arg:ident from_ref_type) => (reencoder.ref_type($arg)?);
1648            (map $arg:ident to_ref_type) => (reencoder.ref_type($arg)?);
1649            (map $arg:ident memarg) => (reencoder.mem_arg($arg));
1650            (map $arg:ident ordering) => (reencoder.ordering($arg));
1651            (map $arg:ident local_index) => ($arg);
1652            (map $arg:ident value) => ($arg);
1653            (map $arg:ident lane) => ($arg);
1654            (map $arg:ident lanes) => ($arg);
1655            (map $arg:ident array_size) => ($arg);
1656            (map $arg:ident field_index) => ($arg);
1657            (map $arg:ident try_table) => ($arg);
1658            (map $arg:ident argument_index) => (reencoder.type_index($arg));
1659            (map $arg:ident result_index) => (reencoder.type_index($arg));
1660            (map $arg:ident cont_type_index) => (reencoder.type_index($arg));
1661            (map $arg:ident resume_table) => ((
1662                $arg.handlers.into_iter().map(|h| reencoder.handle(h)).collect::<Vec<_>>().into()
1663            ));
1664
1665            // This case takes the arguments of a wasmparser instruction and creates
1666            // a wasm-encoder instruction. There are a few special cases for where
1667            // the structure of a wasmparser instruction differs from that of
1668            // wasm-encoder.
1669            (build $op:ident) => (Instruction::$op);
1670            (build BrTable $arg:ident) => (Instruction::BrTable($arg.0, $arg.1));
1671            (build TypedSelectMulti $arg:ident) => (Instruction::TypedSelectMulti(Cow::from($arg)));
1672            (build I32Const $arg:ident) => (Instruction::I32Const($arg));
1673            (build I64Const $arg:ident) => (Instruction::I64Const($arg));
1674            (build F32Const $arg:ident) => (Instruction::F32Const($arg.into()));
1675            (build F64Const $arg:ident) => (Instruction::F64Const($arg.into()));
1676            (build V128Const $arg:ident) => (Instruction::V128Const($arg.i128()));
1677            (build TryTable $table:ident) => (Instruction::TryTable(reencoder.block_type($table.ty)?, {
1678                $table.catches.into_iter().map(|c| reencoder.catch(c)).collect::<Vec<_>>().into()
1679            }));
1680            (build $op:ident $arg:ident) => (Instruction::$op($arg));
1681            (build $op:ident $($arg:ident)*) => (Instruction::$op { $($arg),* });
1682        }
1683
1684        wasmparser::for_each_operator!(translate)
1685    }
1686
1687    /// Parses the input `section` given from the `wasmparser` crate and adds
1688    /// all the code to the `code` section.
1689    pub fn parse_code_section<T: ?Sized + Reencode>(
1690        reencoder: &mut T,
1691        code: &mut crate::CodeSection,
1692        section: wasmparser::CodeSectionReader<'_>,
1693    ) -> Result<(), Error<T::Error>> {
1694        for func in section {
1695            reencoder.parse_function_body(code, func?)?;
1696        }
1697        Ok(())
1698    }
1699
1700    /// Parses a single [`wasmparser::FunctionBody`] and adds it to the `code` section.
1701    pub fn parse_function_body<T: ?Sized + Reencode>(
1702        reencoder: &mut T,
1703        code: &mut crate::CodeSection,
1704        func: wasmparser::FunctionBody<'_>,
1705    ) -> Result<(), Error<T::Error>> {
1706        let mut f = reencoder.new_function_with_parsed_locals(&func)?;
1707        let mut reader = func.get_operators_reader()?;
1708        while !reader.eof() {
1709            f.instruction(&reencoder.parse_instruction(&mut reader)?);
1710        }
1711        code.function(&f);
1712        Ok(())
1713    }
1714
1715    /// Create a new [`crate::Function`] by parsing the locals declarations from the
1716    /// provided [`wasmparser::FunctionBody`].
1717    pub fn new_function_with_parsed_locals<T: ?Sized + Reencode>(
1718        reencoder: &mut T,
1719        func: &wasmparser::FunctionBody<'_>,
1720    ) -> Result<crate::Function, Error<T::Error>> {
1721        let mut locals = Vec::new();
1722        for pair in func.get_locals_reader()? {
1723            let (cnt, ty) = pair?;
1724            locals.push((cnt, reencoder.val_type(ty)?));
1725        }
1726        Ok(crate::Function::new(locals))
1727    }
1728
1729    /// Parses a single instruction from `reader` and adds it to `function`.
1730    pub fn parse_instruction<'a, T: ?Sized + Reencode>(
1731        reencoder: &mut T,
1732        reader: &mut wasmparser::OperatorsReader<'a>,
1733    ) -> Result<crate::Instruction<'a>, Error<T::Error>> {
1734        let instruction = reencoder.instruction(reader.read()?)?;
1735        Ok(instruction)
1736    }
1737
1738    pub fn parse_unknown_section<T: ?Sized + Reencode>(
1739        _reencoder: &mut T,
1740        module: &mut crate::Module,
1741        id: u8,
1742        contents: &[u8],
1743    ) -> Result<(), Error<T::Error>> {
1744        module.section(&crate::RawSection { id, data: contents });
1745        Ok(())
1746    }
1747
1748    pub fn custom_name_section<T: ?Sized + Reencode>(
1749        reencoder: &mut T,
1750        section: wasmparser::NameSectionReader<'_>,
1751    ) -> Result<crate::NameSection, Error<T::Error>> {
1752        let mut ret = crate::NameSection::new();
1753        for subsection in section {
1754            reencoder.parse_custom_name_subsection(&mut ret, subsection?)?;
1755        }
1756        Ok(ret)
1757    }
1758
1759    pub fn parse_custom_name_subsection<T: ?Sized + Reencode>(
1760        reencoder: &mut T,
1761        names: &mut crate::NameSection,
1762        section: wasmparser::Name<'_>,
1763    ) -> Result<(), Error<T::Error>> {
1764        match section {
1765            wasmparser::Name::Module { name, .. } => {
1766                names.module(name);
1767            }
1768            wasmparser::Name::Function(map) => {
1769                names.functions(&name_map(map, |i| reencoder.function_index(i))?);
1770            }
1771            wasmparser::Name::Type(map) => {
1772                names.types(&name_map(map, |i| reencoder.type_index(i))?);
1773            }
1774            wasmparser::Name::Local(map) => {
1775                names.locals(&indirect_name_map(map, |i| reencoder.function_index(i))?);
1776            }
1777            wasmparser::Name::Label(map) => {
1778                names.labels(&indirect_name_map(map, |i| reencoder.function_index(i))?);
1779            }
1780            wasmparser::Name::Table(map) => {
1781                names.tables(&name_map(map, |i| reencoder.table_index(i))?);
1782            }
1783            wasmparser::Name::Memory(map) => {
1784                names.memories(&name_map(map, |i| reencoder.memory_index(i))?);
1785            }
1786            wasmparser::Name::Global(map) => {
1787                names.globals(&name_map(map, |i| reencoder.global_index(i))?);
1788            }
1789            wasmparser::Name::Element(map) => {
1790                names.elements(&name_map(map, |i| reencoder.element_index(i))?);
1791            }
1792            wasmparser::Name::Data(map) => {
1793                names.data(&name_map(map, |i| reencoder.data_index(i))?);
1794            }
1795            wasmparser::Name::Tag(map) => {
1796                names.tags(&name_map(map, |i| reencoder.tag_index(i))?);
1797            }
1798            wasmparser::Name::Field(map) => {
1799                names.fields(&indirect_name_map(map, |i| reencoder.type_index(i))?);
1800            }
1801            wasmparser::Name::Unknown { ty, data, .. } => {
1802                names.raw(ty, data);
1803            }
1804        }
1805        Ok(())
1806    }
1807
1808    pub fn name_map(
1809        map: wasmparser::NameMap<'_>,
1810        mut map_index: impl FnMut(u32) -> u32,
1811    ) -> wasmparser::Result<crate::NameMap> {
1812        let mut ret = crate::NameMap::new();
1813        for naming in map {
1814            let naming = naming?;
1815            ret.append(map_index(naming.index), naming.name);
1816        }
1817        Ok(ret)
1818    }
1819
1820    pub fn indirect_name_map(
1821        map: wasmparser::IndirectNameMap<'_>,
1822        mut map_index: impl FnMut(u32) -> u32,
1823    ) -> wasmparser::Result<crate::IndirectNameMap> {
1824        let mut ret = crate::IndirectNameMap::new();
1825        for naming in map {
1826            let naming = naming?;
1827            ret.append(map_index(naming.index), &name_map(naming.names, |i| i)?);
1828        }
1829        Ok(ret)
1830    }
1831}
1832
1833impl From<wasmparser::Ieee32> for crate::Ieee32 {
1834    fn from(arg: wasmparser::Ieee32) -> Self {
1835        RoundtripReencoder.ieee32_arg(arg)
1836    }
1837}
1838
1839impl From<wasmparser::Ieee64> for crate::Ieee64 {
1840    fn from(arg: wasmparser::Ieee64) -> Self {
1841        RoundtripReencoder.ieee64_arg(arg)
1842    }
1843}
1844
1845impl From<wasmparser::MemArg> for crate::MemArg {
1846    fn from(arg: wasmparser::MemArg) -> Self {
1847        RoundtripReencoder.mem_arg(arg)
1848    }
1849}
1850
1851impl From<wasmparser::Ordering> for crate::Ordering {
1852    fn from(arg: wasmparser::Ordering) -> Self {
1853        RoundtripReencoder.ordering(arg)
1854    }
1855}
1856
1857impl TryFrom<wasmparser::BlockType> for crate::BlockType {
1858    type Error = Error;
1859
1860    fn try_from(arg: wasmparser::BlockType) -> Result<Self, Self::Error> {
1861        RoundtripReencoder.block_type(arg)
1862    }
1863}
1864
1865impl<'a> TryFrom<wasmparser::Operator<'a>> for crate::Instruction<'a> {
1866    type Error = Error;
1867
1868    fn try_from(arg: wasmparser::Operator<'a>) -> Result<Self, Self::Error> {
1869        RoundtripReencoder.instruction(arg)
1870    }
1871}
1872
1873impl From<wasmparser::Catch> for crate::Catch {
1874    fn from(arg: wasmparser::Catch) -> Self {
1875        RoundtripReencoder.catch(arg)
1876    }
1877}
1878
1879impl<'a> TryFrom<wasmparser::ConstExpr<'a>> for crate::ConstExpr {
1880    type Error = Error;
1881
1882    fn try_from(const_expr: wasmparser::ConstExpr) -> Result<Self, Self::Error> {
1883        RoundtripReencoder.const_expr(const_expr)
1884    }
1885}
1886
1887impl<'a> From<wasmparser::CustomSectionReader<'a>> for crate::CustomSection<'a> {
1888    fn from(section: wasmparser::CustomSectionReader<'a>) -> Self {
1889        RoundtripReencoder.custom_section(section)
1890    }
1891}
1892
1893impl From<wasmparser::ExternalKind> for crate::ExportKind {
1894    fn from(external_kind: wasmparser::ExternalKind) -> Self {
1895        RoundtripReencoder.export_kind(external_kind)
1896    }
1897}
1898
1899impl TryFrom<wasmparser::GlobalType> for crate::GlobalType {
1900    type Error = Error;
1901
1902    fn try_from(global_ty: wasmparser::GlobalType) -> Result<Self, Self::Error> {
1903        RoundtripReencoder.global_type(global_ty)
1904    }
1905}
1906
1907impl From<wasmparser::Handle> for crate::Handle {
1908    fn from(arg: wasmparser::Handle) -> Self {
1909        RoundtripReencoder.handle(arg)
1910    }
1911}
1912
1913impl TryFrom<wasmparser::TypeRef> for crate::EntityType {
1914    type Error = Error;
1915
1916    fn try_from(type_ref: wasmparser::TypeRef) -> Result<Self, Self::Error> {
1917        RoundtripReencoder.entity_type(type_ref)
1918    }
1919}
1920
1921impl From<wasmparser::MemoryType> for crate::MemoryType {
1922    fn from(memory_ty: wasmparser::MemoryType) -> Self {
1923        RoundtripReencoder.memory_type(memory_ty)
1924    }
1925}
1926
1927impl TryFrom<wasmparser::TableType> for crate::TableType {
1928    type Error = Error;
1929
1930    fn try_from(table_ty: wasmparser::TableType) -> Result<Self, Self::Error> {
1931        RoundtripReencoder.table_type(table_ty)
1932    }
1933}
1934
1935impl From<wasmparser::TagKind> for crate::TagKind {
1936    fn from(kind: wasmparser::TagKind) -> Self {
1937        RoundtripReencoder.tag_kind(kind)
1938    }
1939}
1940
1941impl From<wasmparser::TagType> for crate::TagType {
1942    fn from(tag_ty: wasmparser::TagType) -> Self {
1943        RoundtripReencoder.tag_type(tag_ty)
1944    }
1945}
1946
1947impl TryFrom<wasmparser::SubType> for crate::SubType {
1948    type Error = Error;
1949
1950    fn try_from(sub_ty: wasmparser::SubType) -> Result<Self, Self::Error> {
1951        RoundtripReencoder.sub_type(sub_ty)
1952    }
1953}
1954
1955impl TryFrom<wasmparser::CompositeType> for crate::CompositeType {
1956    type Error = Error;
1957
1958    fn try_from(composite_ty: wasmparser::CompositeType) -> Result<Self, Self::Error> {
1959        RoundtripReencoder.composite_type(composite_ty)
1960    }
1961}
1962
1963impl TryFrom<wasmparser::FuncType> for crate::FuncType {
1964    type Error = Error;
1965
1966    fn try_from(func_ty: wasmparser::FuncType) -> Result<Self, Self::Error> {
1967        RoundtripReencoder.func_type(func_ty)
1968    }
1969}
1970
1971impl TryFrom<wasmparser::ArrayType> for crate::ArrayType {
1972    type Error = Error;
1973
1974    fn try_from(array_ty: wasmparser::ArrayType) -> Result<Self, Self::Error> {
1975        RoundtripReencoder.array_type(array_ty)
1976    }
1977}
1978
1979impl TryFrom<wasmparser::StructType> for crate::StructType {
1980    type Error = Error;
1981
1982    fn try_from(struct_ty: wasmparser::StructType) -> Result<Self, Self::Error> {
1983        RoundtripReencoder.struct_type(struct_ty)
1984    }
1985}
1986
1987impl TryFrom<wasmparser::FieldType> for crate::FieldType {
1988    type Error = Error;
1989
1990    fn try_from(field_ty: wasmparser::FieldType) -> Result<Self, Self::Error> {
1991        RoundtripReencoder.field_type(field_ty)
1992    }
1993}
1994
1995impl TryFrom<wasmparser::StorageType> for crate::StorageType {
1996    type Error = Error;
1997
1998    fn try_from(storage_ty: wasmparser::StorageType) -> Result<Self, Self::Error> {
1999        RoundtripReencoder.storage_type(storage_ty)
2000    }
2001}
2002
2003impl TryFrom<wasmparser::ValType> for crate::ValType {
2004    type Error = Error;
2005
2006    fn try_from(val_ty: wasmparser::ValType) -> Result<Self, Self::Error> {
2007        RoundtripReencoder.val_type(val_ty)
2008    }
2009}
2010
2011impl TryFrom<wasmparser::RefType> for crate::RefType {
2012    type Error = Error;
2013
2014    fn try_from(ref_type: wasmparser::RefType) -> Result<Self, Self::Error> {
2015        RoundtripReencoder.ref_type(ref_type)
2016    }
2017}
2018
2019impl TryFrom<wasmparser::HeapType> for crate::HeapType {
2020    type Error = Error;
2021
2022    fn try_from(heap_type: wasmparser::HeapType) -> Result<Self, Self::Error> {
2023        crate::reencode::utils::heap_type(&mut crate::reencode::RoundtripReencoder, heap_type)
2024    }
2025}
2026
2027impl From<wasmparser::AbstractHeapType> for crate::AbstractHeapType {
2028    fn from(value: wasmparser::AbstractHeapType) -> Self {
2029        RoundtripReencoder.abstract_heap_type(value)
2030    }
2031}