golem_wasm_ast/core/
mod.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::{
16    metadata, new_core_section_cache, AstCustomization, IndexSpace, Section, SectionCache,
17    SectionIndex, SectionType, Sections,
18};
19use mappable_rc::Mrc;
20use std::fmt::{Debug, Formatter};
21
22#[cfg(feature = "parser")]
23pub mod parser;
24#[cfg(feature = "writer")]
25pub mod writer;
26
27pub type DataIdx = u32;
28pub type ElemIdx = u32;
29pub type ExportIdx = u32;
30pub type FuncIdx = u32;
31pub type GlobalIdx = u32;
32pub type LabelIdx = u32;
33pub type LocalIdx = u32;
34pub type MemIdx = u32;
35pub type TableIdx = u32;
36pub type TypeIdx = u32;
37
38/// Trait to be implemented by custom Custom node types in order to provide information
39/// for the metadata feature [Module::get_metadata].
40pub trait RetainsCustomSection {
41    fn name(&self) -> &str;
42    fn data(&self) -> &[u8];
43}
44
45/// The core section nodes
46///
47/// See [Section] for more information.
48#[derive(Debug, Clone, PartialEq)]
49pub enum CoreSection<Ast: AstCustomization> {
50    Type(FuncType),
51    Func(FuncTypeRef),
52    Code(FuncCode<Ast::Expr>),
53    Table(Table),
54    Mem(Mem),
55    Global(Global),
56    Elem(Elem<Ast::Expr>),
57    Data(Ast::Data),
58    DataCount(DataCount),
59    Start(Start),
60    Export(Export),
61    Import(Import),
62    Custom(Ast::Custom),
63}
64
65#[allow(unused)]
66impl<Ast: AstCustomization> CoreSection<Ast> {
67    pub fn as_type(&self) -> &FuncType {
68        match self {
69            CoreSection::Type(ty) => ty,
70            _ => panic!("Expected type section, got {}", self.type_name()),
71        }
72    }
73
74    pub fn as_func(&self) -> &FuncTypeRef {
75        match self {
76            CoreSection::Func(func) => func,
77            _ => panic!("Expected func section, got {}", self.type_name()),
78        }
79    }
80
81    pub fn as_code(&self) -> &FuncCode<Ast::Expr> {
82        match self {
83            CoreSection::Code(code) => code,
84            _ => panic!("Expected code section, got {}", self.type_name()),
85        }
86    }
87
88    pub fn as_table(&self) -> &Table {
89        match self {
90            CoreSection::Table(table) => table,
91            _ => panic!("Expected table section, got {}", self.type_name()),
92        }
93    }
94
95    pub fn as_mem(&self) -> &Mem {
96        match self {
97            CoreSection::Mem(mem) => mem,
98            _ => panic!("Expected mem section, got {}", self.type_name()),
99        }
100    }
101
102    pub fn as_global(&self) -> &Global {
103        match self {
104            CoreSection::Global(global) => global,
105            _ => panic!("Expected global section, got {}", self.type_name()),
106        }
107    }
108
109    pub fn as_elem(&self) -> &Elem<Ast::Expr> {
110        match self {
111            CoreSection::Elem(elem) => elem,
112            _ => panic!("Expected elem section, got {}", self.type_name()),
113        }
114    }
115
116    pub fn as_data(&self) -> &Ast::Data {
117        match self {
118            CoreSection::Data(data) => data,
119            _ => panic!("Expected data section, got {}", self.type_name()),
120        }
121    }
122
123    pub fn as_data_count(&self) -> &DataCount {
124        match self {
125            CoreSection::DataCount(data_count) => data_count,
126            _ => panic!("Expected data count section, got {}", self.type_name()),
127        }
128    }
129
130    pub fn as_start(&self) -> &Start {
131        match self {
132            CoreSection::Start(start) => start,
133            _ => panic!("Expected start section, got {}", self.type_name()),
134        }
135    }
136
137    pub fn as_export(&self) -> &Export {
138        match self {
139            CoreSection::Export(export) => export,
140            _ => panic!("Expected export section, got {}", self.type_name()),
141        }
142    }
143
144    pub fn as_import(&self) -> &Import {
145        match self {
146            CoreSection::Import(import) => import,
147            _ => panic!("Expected import section, got {}", self.type_name()),
148        }
149    }
150
151    pub fn as_custom(&self) -> &Ast::Custom {
152        match self {
153            CoreSection::Custom(custom) => custom,
154            _ => panic!("Expected custom section, got {}", self.type_name()),
155        }
156    }
157
158    pub fn type_name(&self) -> &'static str {
159        match self {
160            CoreSection::Type(_) => "type",
161            CoreSection::Func(_) => "func",
162            CoreSection::Code(_) => "code",
163            CoreSection::Table(_) => "table",
164            CoreSection::Mem(_) => "mem",
165            CoreSection::Global(_) => "global",
166            CoreSection::Elem(_) => "elem",
167            CoreSection::Data(_) => "data",
168            CoreSection::DataCount(_) => "data count",
169            CoreSection::Start(_) => "start",
170            CoreSection::Export(_) => "export",
171            CoreSection::Import(_) => "import",
172            CoreSection::Custom(_) => "custom",
173        }
174    }
175}
176
177impl<Ast: AstCustomization> Section<CoreIndexSpace, CoreSectionType> for CoreSection<Ast> {
178    fn index_space(&self) -> CoreIndexSpace {
179        match self {
180            CoreSection::Type(inner) => inner.index_space(),
181            CoreSection::Func(inner) => inner.index_space(),
182            CoreSection::Code(inner) => inner.index_space(),
183            CoreSection::Table(inner) => inner.index_space(),
184            CoreSection::Mem(inner) => inner.index_space(),
185            CoreSection::Global(inner) => inner.index_space(),
186            CoreSection::Elem(inner) => inner.index_space(),
187            CoreSection::Data(inner) => inner.index_space(),
188            CoreSection::DataCount(inner) => inner.index_space(),
189            CoreSection::Start(inner) => inner.index_space(),
190            CoreSection::Export(inner) => inner.index_space(),
191            CoreSection::Import(inner) => inner.index_space(),
192            CoreSection::Custom(inner) => inner.index_space(),
193        }
194    }
195
196    fn section_type(&self) -> CoreSectionType {
197        match self {
198            CoreSection::Type(inner) => inner.section_type(),
199            CoreSection::Func(inner) => inner.section_type(),
200            CoreSection::Code(inner) => inner.section_type(),
201            CoreSection::Table(inner) => inner.section_type(),
202            CoreSection::Mem(inner) => inner.section_type(),
203            CoreSection::Global(inner) => inner.section_type(),
204            CoreSection::Elem(inner) => inner.section_type(),
205            CoreSection::Data(inner) => inner.section_type(),
206            CoreSection::DataCount(inner) => inner.section_type(),
207            CoreSection::Start(inner) => inner.section_type(),
208            CoreSection::Export(inner) => inner.section_type(),
209            CoreSection::Import(inner) => inner.section_type(),
210            CoreSection::Custom(inner) => inner.section_type(),
211        }
212    }
213}
214
215/// The core section types
216///
217/// See [SectionType] for more information.
218#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
219pub enum CoreSectionType {
220    Type,
221    Func,
222    Code,
223    Table,
224    Mem,
225    Global,
226    Elem,
227    Data,
228    DataCount,
229    Start,
230    Export,
231    Import,
232    Custom,
233}
234
235impl SectionType for CoreSectionType {
236    fn allow_grouping(&self) -> bool {
237        match self {
238            CoreSectionType::Type => true,
239            CoreSectionType::Func => true,
240            CoreSectionType::Code => true,
241            CoreSectionType::Table => true,
242            CoreSectionType::Mem => true,
243            CoreSectionType::Global => true,
244            CoreSectionType::Elem => true,
245            CoreSectionType::Data => true,
246            CoreSectionType::DataCount => false,
247            CoreSectionType::Start => false,
248            CoreSectionType::Export => true,
249            CoreSectionType::Import => true,
250            CoreSectionType::Custom => false,
251        }
252    }
253}
254
255/// The core index space
256///
257/// See [IndexSpace] for more information.
258#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
259pub enum CoreIndexSpace {
260    Type,
261    Func,
262    Table,
263    Mem,
264    Global,
265    Elem,
266    Data,
267    Local,
268    Label,
269    Code,
270    Export,
271    Start,
272    Custom,
273}
274
275impl IndexSpace for CoreIndexSpace {
276    type Index = u32;
277}
278
279/// Number types classify numeric values.
280///
281/// The types i32 and i64 classify 32 and 64 bit integers, respectively. Integers are not inherently signed or unsigned,
282/// their interpretation is determined by individual operations.
283///
284/// The types f32 and f64 classify 32 and 64 bit floating-point data, respectively. They correspond to the respective
285/// binary floating-point representations, also known as single and double precision, as defined by the IEEE 754
286/// standard (Section 3.3).
287///
288/// Number types are transparent, meaning that their bit patterns can be observed. Values of number type can be stored
289/// in memories.
290#[derive(Debug, Clone, PartialEq, Eq)]
291pub enum NumType {
292    I32,
293    I64,
294    F32,
295    F64,
296}
297
298/// Vector types classify vectors of numeric values processed by vector instructions (also known as SIMD instructions,
299/// single instruction multiple data).
300///
301/// The type v128 corresponds to a 128 bit vector of packed integer or floating-point data. The packed data can be
302/// interpreted as signed or unsigned integers, single or double precision floating-point values, or a single 128 bit
303/// type. The interpretation is determined by individual operations.
304///
305/// Vector types, like number types are transparent, meaning that their bit patterns can be observed. Values of vector
306/// type can be stored in memories.
307#[derive(Debug, Clone, PartialEq, Eq)]
308pub enum VecType {
309    V128,
310}
311
312/// Reference types classify first-class references to objects in the runtime store.
313///
314/// The type funcref denotes the infinite union of all references to functions, regardless of their function types.
315///
316/// The type externref denotes the infinite union of all references to objects owned by the embedder and that can be
317/// passed into WebAssembly under this type.
318///
319/// Reference types are opaque, meaning that neither their size nor their bit pattern can be observed. Values of
320/// reference type can be stored in tables.
321///
322#[derive(Debug, Clone, PartialEq, Eq)]
323pub enum RefType {
324    FuncRef,
325    ExternRef,
326}
327
328/// Value types classify the individual values that WebAssembly code can compute with and the values that a variable
329/// accepts. They are either number types, vector types, or reference types.
330#[derive(Debug, Clone, PartialEq, Eq)]
331pub enum ValType {
332    Num(NumType),
333    Vec(VecType),
334    Ref(RefType),
335}
336
337#[derive(Debug, Clone, PartialEq, Eq)]
338pub enum NumOrVecType {
339    Num(NumType),
340    Vec(VecType),
341}
342
343/// Result types classify the result of executing instructions or functions, which is a sequence of values, written with
344/// brackets.
345#[derive(Debug, Clone, PartialEq, Eq)]
346pub struct ResultType {
347    pub values: Vec<ValType>,
348}
349
350/// Function types classify the signature of functions, mapping a vector of parameters to a vector of results. They are
351/// also used to classify the inputs and outputs of instructions.
352#[derive(Debug, Clone, PartialEq, Eq)]
353pub struct FuncType {
354    pub input: ResultType,
355    pub output: ResultType,
356}
357
358impl Section<CoreIndexSpace, CoreSectionType> for FuncType {
359    fn index_space(&self) -> CoreIndexSpace {
360        CoreIndexSpace::Type
361    }
362
363    fn section_type(&self) -> CoreSectionType {
364        CoreSectionType::Type
365    }
366}
367
368/// Limits classify the size range of resizeable storage associated with memory types and table types.
369///
370/// If no maximum is given, the respective storage can grow to any size.
371///
372#[derive(Debug, Clone, PartialEq, Eq)]
373pub struct Limits {
374    pub min: u64,
375    pub max: Option<u64>,
376}
377
378/// Memory types classify linear memories and their size range.
379///
380/// The limits constrain the minimum and optionally the maximum size of a memory. The limits are given in units of page
381/// size.
382#[derive(Debug, Clone, PartialEq, Eq)]
383pub struct MemType {
384    pub limits: Limits,
385}
386
387/// Table types classify tables over elements of reference type within a size range.
388///
389/// Like memories, tables are constrained by limits for their minimum and optionally maximum size. The limits are given
390/// in numbers of entries.
391#[derive(Debug, Clone, PartialEq, Eq)]
392pub struct TableType {
393    pub limits: Limits,
394    pub elements: RefType,
395}
396
397#[derive(Debug, Clone, PartialEq, Eq)]
398pub enum Mut {
399    Const,
400    Var,
401}
402
403/// Global types classify global variables, which hold a value and can either be mutable or immutable.
404#[derive(Debug, Clone, PartialEq, Eq)]
405pub struct GlobalType {
406    pub mutability: Mut,
407    pub val_type: ValType,
408}
409
410/// External types classify imports and external values with their respective types.
411#[derive(Debug, Clone, PartialEq, Eq)]
412pub enum ExternType {
413    Func(FuncType),
414    Table(TableType),
415    Mem(MemType),
416    Global(GlobalType),
417}
418
419#[derive(Debug, Clone, PartialEq, Eq)]
420pub struct FuncTypeRef {
421    pub type_idx: TypeIdx,
422}
423
424impl Section<CoreIndexSpace, CoreSectionType> for FuncTypeRef {
425    fn index_space(&self) -> CoreIndexSpace {
426        CoreIndexSpace::Func
427    }
428
429    fn section_type(&self) -> CoreSectionType {
430        CoreSectionType::Func
431    }
432}
433
434#[derive(Debug, Clone, PartialEq)]
435pub struct FuncCode<Expr> {
436    pub locals: Vec<ValType>,
437    pub body: Expr,
438}
439
440impl<Expr: Debug + Clone + PartialEq> Section<CoreIndexSpace, CoreSectionType> for FuncCode<Expr> {
441    fn index_space(&self) -> CoreIndexSpace {
442        CoreIndexSpace::Func
443    }
444
445    fn section_type(&self) -> CoreSectionType {
446        CoreSectionType::Code
447    }
448}
449
450/// The funcs component of a module defines a vector of functions with the following structure.
451///
452/// Functions are referenced through function indices, starting with the smallest index not referencing a function
453/// import.
454///
455/// `typ` is the type of a function declares its signature by reference to a type defined in the module. The parameters of the
456/// function are referenced through 0-based local indices in the function’s body; they are mutable.
457///
458/// The `locals` declare a vector of mutable local variables and their types. These variables are referenced through
459/// local indices in the function’s body. The index of the first local is the smallest index not referencing a
460/// parameter.
461///
462/// The `body` is an instruction sequence that upon termination must produce a stack matching the function type’s result
463/// type.
464/// /
465#[derive(Debug, Clone, PartialEq)]
466pub struct Func<Expr: 'static> {
467    pub type_idx: TypeIdx,
468    code: Mrc<FuncCode<Expr>>,
469}
470
471impl<Expr: 'static> Func<Expr> {
472    pub fn locals(&self) -> Mrc<Vec<ValType>> {
473        Mrc::map(self.code.clone(), |code| &code.locals)
474    }
475
476    pub fn body(&self) -> Mrc<Expr> {
477        Mrc::map(self.code.clone(), |code| &code.body)
478    }
479}
480
481/// The tables component of a module defines a vector of tables described by their table type:
482///
483/// A table is a vector of opaque values of a particular reference type. The size in the limits of the table type
484/// specifies the initial size of that table, while its max, if present, restricts the size to which it can grow later.
485///
486/// Tables can be initialized through element segments.
487///
488/// Tables are referenced through table indices, starting with the smallest index not referencing a table import. Most
489/// constructs implicitly reference table index 0.
490///
491#[derive(Debug, Clone, PartialEq, Eq)]
492pub struct Table {
493    pub table_type: TableType,
494}
495
496impl Section<CoreIndexSpace, CoreSectionType> for Table {
497    fn index_space(&self) -> CoreIndexSpace {
498        CoreIndexSpace::Table
499    }
500
501    fn section_type(&self) -> CoreSectionType {
502        CoreSectionType::Table
503    }
504}
505
506/// The mems component of a module defines a vector of linear memories (or memories for short) as described by their
507/// memory type:
508///
509/// A memory is a vector of raw uninterpreted bytes. The size in the limits of the memory type specifies the initial
510/// size of that memory, while its max, if present, restricts the size to which it can grow later. Both are in units of
511/// page size.
512///
513/// Memories can be initialized through data segments.
514///
515/// Memories are referenced through memory indices, starting with the smallest index not referencing a memory import.
516/// Most constructs implicitly reference memory index 0.
517///
518#[derive(Debug, Clone, PartialEq, Eq)]
519pub struct Mem {
520    pub mem_type: MemType,
521}
522
523impl Section<CoreIndexSpace, CoreSectionType> for Mem {
524    fn index_space(&self) -> CoreIndexSpace {
525        CoreIndexSpace::Mem
526    }
527
528    fn section_type(&self) -> CoreSectionType {
529        CoreSectionType::Mem
530    }
531}
532
533/// The globals component of a module defines a vector of global variables (or globals for short):
534///
535/// Each global stores a single value of the given global type. Its type also specifies whether a global is immutable or
536/// mutable. Moreover, each global is initialized with an value given by a constant initializer expression.
537///
538/// Globals are referenced through global indices, starting with the smallest index not referencing a global import.
539#[derive(Debug, Clone, PartialEq)]
540pub struct Global {
541    pub global_type: GlobalType,
542    pub init: Expr,
543}
544
545impl Section<CoreIndexSpace, CoreSectionType> for Global {
546    fn index_space(&self) -> CoreIndexSpace {
547        CoreIndexSpace::Global
548    }
549
550    fn section_type(&self) -> CoreSectionType {
551        CoreSectionType::Global
552    }
553}
554
555#[derive(Debug, Clone, PartialEq)]
556pub enum ElemMode {
557    Passive,
558    Active { table_idx: TableIdx, offset: Expr },
559    Declarative,
560}
561
562/// The initial contents of a table is uninitialized. Element segments can be used to initialize a subrange of a table
563/// from a static vector of elements.
564///
565/// The elems component of a module defines a vector of element segments. Each element segment defines a reference type
566/// and a corresponding list of constant element expressions.
567///
568/// Element segments have a mode that identifies them as either passive, active, or declarative. A passive element
569/// segment’s elements can be copied to a table using the table.init instruction. An active element segment copies its
570/// elements into a table during instantiation, as specified by a table index and a constant expression defining an
571/// offset into that table. A declarative element segment is not available at runtime but merely serves to
572/// forward-declare references that are formed in code with instructions like ref.func.
573///
574/// Element segments are referenced through element indices.
575///
576#[derive(Debug, Clone, PartialEq)]
577pub struct Elem<Expr> {
578    pub ref_type: RefType,
579    pub init: Vec<Expr>,
580    pub mode: ElemMode,
581}
582
583impl<Expr: Debug + Clone + PartialEq> Section<CoreIndexSpace, CoreSectionType> for Elem<Expr> {
584    fn index_space(&self) -> CoreIndexSpace {
585        CoreIndexSpace::Elem
586    }
587
588    fn section_type(&self) -> CoreSectionType {
589        CoreSectionType::Elem
590    }
591}
592
593#[derive(Debug, Clone, PartialEq)]
594pub enum DataMode<Expr> {
595    Passive,
596    Active { memory: MemIdx, offset: Expr },
597}
598
599/// The initial contents of a memory are zero bytes. Data segments can be used to initialize a range of memory from a
600/// static vector of bytes.
601///
602/// The datas component of a module defines a vector of data segments.
603///
604/// Like element segments, data segments have a mode that identifies them as either passive or active. A passive data
605/// segment’s contents can be copied into a memory using the memory.init instruction. An active data segment copies its
606/// contents into a memory during instantiation, as specified by a memory index and a constant expression defining an
607/// offset into that memory.
608///
609/// Data segments are referenced through data indices.
610///
611#[derive(Debug, Clone, PartialEq)]
612pub struct Data<Expr: Clone> {
613    init: Vec<u8>,
614    mode: DataMode<Expr>,
615}
616
617impl<Expr: Debug + Clone + PartialEq> Section<CoreIndexSpace, CoreSectionType> for Data<Expr> {
618    fn index_space(&self) -> CoreIndexSpace {
619        CoreIndexSpace::Data
620    }
621
622    fn section_type(&self) -> CoreSectionType {
623        CoreSectionType::Data
624    }
625}
626
627#[derive(Debug, Clone, PartialEq, Eq)]
628pub struct DataCount {
629    pub count: u32,
630}
631
632impl Section<CoreIndexSpace, CoreSectionType> for DataCount {
633    fn index_space(&self) -> CoreIndexSpace {
634        CoreIndexSpace::Data
635    }
636
637    fn section_type(&self) -> CoreSectionType {
638        CoreSectionType::DataCount
639    }
640}
641
642/// The start component of a module declares the function index of a start function that is automatically invoked when
643/// the module is instantiated, after tables and memories have been initialized.
644#[derive(Debug, Clone, PartialEq, Eq)]
645pub struct Start {
646    pub func: FuncIdx,
647}
648
649impl Section<CoreIndexSpace, CoreSectionType> for Start {
650    fn index_space(&self) -> CoreIndexSpace {
651        CoreIndexSpace::Start
652    }
653
654    fn section_type(&self) -> CoreSectionType {
655        CoreSectionType::Start
656    }
657}
658
659#[derive(Debug, Clone, PartialEq, Eq)]
660pub enum ExportDesc {
661    Func(FuncIdx),
662    Table(TableIdx),
663    Mem(MemIdx),
664    Global(GlobalIdx),
665}
666
667/// The exports component of a module defines a set of exports that become accessible to the host environment once the
668/// module has been instantiated.
669///
670/// Each export is labeled by a unique name. Exportable definitions are functions, tables, memories, and globals, which
671/// are referenced through a respective descriptor.
672///
673#[derive(Debug, Clone, PartialEq, Eq)]
674pub struct Export {
675    pub name: String,
676    pub desc: ExportDesc,
677}
678
679impl Section<CoreIndexSpace, CoreSectionType> for Export {
680    fn index_space(&self) -> CoreIndexSpace {
681        CoreIndexSpace::Export
682    }
683
684    fn section_type(&self) -> CoreSectionType {
685        CoreSectionType::Export
686    }
687}
688
689#[derive(Debug, Clone, PartialEq, Eq)]
690pub enum TypeRef {
691    Func(TypeIdx),
692    Table(TableType),
693    Mem(MemType),
694    Global(GlobalType),
695}
696
697/// The imports component of a module defines a set of imports that are required for instantiation.
698///
699/// Each import is labeled by a two-level name space, consisting of a module name and a name for an entity within that
700/// module. Importable definitions are functions, tables, memories, and globals. Each import is specified by a
701/// descriptor with a respective type that a definition provided during instantiation is required to match.
702///
703/// Every import defines an index in the respective index space. In each index space, the indices of imports go before
704/// the first index of any definition contained in the module itself.
705///
706#[derive(Debug, Clone, PartialEq, Eq)]
707pub struct Import {
708    pub module: String,
709    pub name: String,
710    pub desc: TypeRef,
711}
712
713impl Section<CoreIndexSpace, CoreSectionType> for Import {
714    fn index_space(&self) -> CoreIndexSpace {
715        CoreIndexSpace::Func
716    }
717
718    fn section_type(&self) -> CoreSectionType {
719        CoreSectionType::Import
720    }
721}
722
723#[derive(Debug, Clone, PartialEq, Eq)]
724pub struct Custom {
725    pub name: String,
726    pub data: Vec<u8>,
727}
728
729impl RetainsCustomSection for Custom {
730    fn name(&self) -> &str {
731        &self.name
732    }
733
734    fn data(&self) -> &[u8] {
735        &self.data
736    }
737}
738
739impl Section<CoreIndexSpace, CoreSectionType> for Custom {
740    fn index_space(&self) -> CoreIndexSpace {
741        CoreIndexSpace::Custom
742    }
743
744    fn section_type(&self) -> CoreSectionType {
745        CoreSectionType::Custom
746    }
747}
748
749#[derive(Debug, Clone, PartialEq)]
750pub struct Expr {
751    pub instrs: Vec<Instr>,
752}
753
754pub trait ExprSource: IntoIterator<Item = Result<Instr, String>> {
755    fn unparsed(self) -> Result<Vec<u8>, String>;
756}
757
758pub trait RetainsInstructions {
759    fn instructions(&self) -> &[Instr];
760}
761
762pub trait TryFromExprSource {
763    fn try_from<S: ExprSource>(value: S) -> Result<Self, String>
764    where
765        Self: Sized;
766}
767
768impl TryFromExprSource for Expr {
769    fn try_from<S: ExprSource>(value: S) -> Result<Self, String> {
770        let instrs = value.into_iter().collect::<Result<Vec<Instr>, String>>()?;
771        Ok(Self { instrs })
772    }
773}
774
775impl RetainsInstructions for Expr {
776    fn instructions(&self) -> &[Instr] {
777        &self.instrs
778    }
779}
780
781#[derive(Debug, Clone, PartialEq, Eq)]
782pub enum IntWidth {
783    I32,
784    I64,
785}
786
787#[derive(Debug, Clone, PartialEq, Eq)]
788pub enum FloatWidth {
789    F32,
790    F64,
791}
792
793#[derive(Debug, Clone, PartialEq, Eq)]
794pub enum Signedness {
795    Signed,
796    Unsigned,
797}
798
799#[derive(Debug, Clone, PartialEq, Eq)]
800pub enum IShape {
801    I8x16,
802    I16x8,
803    I32x4,
804    I64x2,
805}
806
807#[derive(Debug, Clone, PartialEq, Eq)]
808pub enum FShape {
809    F32x4,
810    F64x2,
811}
812
813#[derive(Debug, Clone, PartialEq, Eq)]
814pub enum Shape {
815    Int(IShape),
816    Float(FShape),
817}
818
819#[derive(Debug, Clone, PartialEq, Eq)]
820pub enum Half {
821    Low,
822    High,
823}
824
825#[derive(Debug, Clone, PartialEq, Eq)]
826pub struct MemArg {
827    pub align: u8,
828    pub offset: u32,
829}
830
831#[derive(Debug, Clone, PartialEq, Eq)]
832pub enum VectorLoadShape {
833    WW8,
834    WW16,
835    WW32,
836    WW64,
837}
838
839#[derive(Debug, Clone, PartialEq, Eq)]
840pub enum BlockType {
841    None,
842    Index(TypeIdx),
843    Value(ValType),
844}
845
846pub type LaneIdx = u8;
847
848#[derive(Debug, Clone, PartialEq)]
849pub enum Instr {
850    // NumericInstr
851    I32Const(i32),
852    I64Const(i64),
853    F32Const(f32),
854    F64Const(f64),
855
856    // ITestOp
857    IEqz(IntWidth),
858
859    // IRelOp
860    IEq(IntWidth),
861    INe(IntWidth),
862    ILt(IntWidth, Signedness),
863    IGt(IntWidth, Signedness),
864    ILe(IntWidth, Signedness),
865    IGe(IntWidth, Signedness),
866
867    // FRelOp
868    FEq(FloatWidth),
869    FNe(FloatWidth),
870    FLt(FloatWidth),
871    FGt(FloatWidth),
872    FLe(FloatWidth),
873    FGe(FloatWidth),
874
875    // IUnOp
876    IClz(IntWidth),
877    ICtz(IntWidth),
878    IPopCnt(IntWidth),
879
880    // IBinOp
881    IAdd(IntWidth),
882    ISub(IntWidth),
883    IMul(IntWidth),
884    IDiv(IntWidth, Signedness),
885    IRem(IntWidth, Signedness),
886    IAnd(IntWidth),
887    IOr(IntWidth),
888    IXor(IntWidth),
889    IShl(IntWidth),
890    IShr(IntWidth, Signedness),
891    IRotL(IntWidth),
892    IRotR(IntWidth),
893
894    // FUnOp
895    FAbs(FloatWidth),
896    FNeg(FloatWidth),
897    FCeil(FloatWidth),
898    FFloor(FloatWidth),
899    FTrunc(FloatWidth),
900    FNearest(FloatWidth),
901
902    // FBinOp
903    FSqrt(FloatWidth),
904    FAdd(FloatWidth),
905    FSub(FloatWidth),
906    FMul(FloatWidth),
907    FDiv(FloatWidth),
908    FMin(FloatWidth),
909    FMax(FloatWidth),
910    FCopySign(FloatWidth),
911
912    I32WrapI64,
913
914    ITruncF(IntWidth, FloatWidth, Signedness),
915
916    I64ExtendI32(Signedness),
917    I64Extend32S,
918    IExtend8S(IntWidth),
919    IExtend16S(IntWidth),
920
921    FConvertI(FloatWidth, IntWidth, Signedness),
922
923    F32DemoteF64,
924    F64PromoteF32,
925
926    IReinterpretF(IntWidth),
927    FReinterpretI(FloatWidth),
928
929    ITruncSatF(IntWidth, FloatWidth, Signedness),
930
931    // VectorInstr
932    V128Const(i128),
933
934    // VVUnOp
935    V128Not,
936
937    // VVBinOp
938    V128And,
939    V128AndNot,
940    V128Or,
941    V128XOr,
942
943    // VVTernOp
944    V128BitSelect,
945
946    // VVTestOp
947    V128AnyTrue,
948
949    VI8x16Shuffle([LaneIdx; 16]),
950
951    VI18x16Swizzle,
952    VSplat(Shape),
953    VI8x16ExtractLane(Signedness, LaneIdx),
954    VI16x8ExtractLane(Signedness, LaneIdx),
955    VI32x4ExtractLane(LaneIdx),
956    VI64x2ExtractLane(LaneIdx),
957    VFExtractLane(FShape, LaneIdx),
958    VReplaceLane(Shape, LaneIdx),
959
960    // VIRelOp
961    VIEq(IShape),
962    VINe(IShape),
963    VILt(IShape, Signedness),
964    VIGt(IShape, Signedness),
965    VILe(IShape, Signedness),
966    VIGe(IShape, Signedness),
967    VI64x2Lt,
968    VI64x2Gt,
969    VI64x2Le,
970    VI64x2Ge,
971
972    // VFRelOp
973    VFEq(FShape),
974    VFNe(FShape),
975    VFLt(FShape),
976    VFGt(FShape),
977    VFLe(FShape),
978    VFGe(FShape),
979
980    // VIUnOp
981    VIAbs(IShape),
982    VINeg(IShape),
983
984    VI8x16PopCnt,
985    VI16x8Q15MulrSat,
986    VI32x4DotI16x8,
987
988    // VFUnOp
989    VFAbs(FShape),
990    VFNeg(FShape),
991    VFSqrt(FShape),
992    VFCeil(FShape),
993    VFFloor(FShape),
994    VFTrunc(FShape),
995    VFNearest(FShape),
996
997    // VITestOp
998    VIAllTrue(IShape),
999
1000    VIBitMask(IShape),
1001
1002    VI8x16NarrowI16x8(Signedness),
1003    VI16x8NarrowI32x4(Signedness),
1004
1005    VI16x8ExtendI8x16(Half, Signedness),
1006    VI32x4ExtendI16x8(Half, Signedness),
1007    VI64x2ExtendI32x4(Half, Signedness),
1008
1009    // VIShiftOp
1010    VIShl(IShape),
1011    VIShr(IShape, Signedness),
1012
1013    // VIBinOp
1014    VIAdd(IShape),
1015    VISub(IShape),
1016
1017    // VIMinMaxOp
1018    VIMin(IShape, Signedness),
1019    VIMax(IShape, Signedness),
1020
1021    // VISatBinOp
1022    VIAddSat(IShape, Signedness),
1023    VISubSat(IShape, Signedness),
1024
1025    VIMul(IShape),
1026    VIAvgr(IShape),
1027    VIExtMul(IShape, Half, Signedness),
1028    VIExtAddPairwise(IShape, Signedness),
1029
1030    // VFBinOp
1031    VFAdd(FShape),
1032    VFSub(FShape),
1033    VFMul(FShape),
1034    VFDiv(FShape),
1035    VFMin(FShape),
1036    VFMax(FShape),
1037    VFPMin(FShape),
1038    VFPMax(FShape),
1039
1040    VI32x4TruncSatF32x4(Signedness),
1041    VI32x4TruncSatF64x2Zero(Signedness),
1042    VI32x4ConvertI32x4(Signedness),
1043    VF32x4DemoteF64x2Zero,
1044    VF64x2ConvertLowI32x4(Signedness),
1045    VF64x2PromoteLowI32x4,
1046
1047    // ReferenceInstr
1048    RefNull(RefType),
1049    RefIsNull,
1050    RefFunc(FuncIdx),
1051
1052    // ParametricInstr
1053    Drop,
1054    Select(Option<Vec<ValType>>),
1055
1056    // VariableInstr
1057    LocalGet(LocalIdx),
1058    LocalSet(LocalIdx),
1059    LocalTee(LocalIdx),
1060    GlobalGet(GlobalIdx),
1061    GlobalSet(GlobalIdx),
1062
1063    // TableInstr
1064    TableGet(TableIdx),
1065    TableSet(TableIdx),
1066    TableSize(TableIdx),
1067    TableGrow(TableIdx),
1068    TableFill(TableIdx),
1069    TableCopy {
1070        source: TableIdx,
1071        destination: TableIdx,
1072    },
1073    TableInit(TableIdx, ElemIdx),
1074    ElemDrop(ElemIdx),
1075
1076    // MemoryInstr
1077    Load(NumOrVecType, MemArg),
1078    Store(NumOrVecType, MemArg),
1079    Load8(NumType, Signedness, MemArg),
1080    Load16(NumType, Signedness, MemArg),
1081    Load32(Signedness, MemArg),
1082    Store8(NumType, MemArg),
1083    Store16(NumType, MemArg),
1084    Store32(MemArg),
1085    V128Load8x8(Signedness, MemArg),
1086    V128Load16x4(Signedness, MemArg),
1087    V128Load32x2(Signedness, MemArg),
1088    V128Load32Zero(MemArg),
1089    V128Load64Zero(MemArg),
1090    V128LoadSplat(VectorLoadShape, MemArg),
1091    V128LoadLane(VectorLoadShape, MemArg, LaneIdx),
1092    V128StoreLane(VectorLoadShape, MemArg, LaneIdx),
1093    MemorySize,
1094    MemoryGrow,
1095    MemoryFill,
1096    MemoryCopy,
1097    MemoryInit(DataIdx),
1098    DataDrop(DataIdx),
1099
1100    // ControlInstr
1101    Nop,
1102    Unreachable,
1103    Block(BlockType, Vec<Instr>),
1104    Loop(BlockType, Vec<Instr>),
1105    If(BlockType, Vec<Instr>, Vec<Instr>),
1106    Br(LabelIdx),
1107    BrIf(LabelIdx),
1108    BrTable(Vec<LabelIdx>, LabelIdx),
1109    Return,
1110    Call(FuncIdx),
1111    CallIndirect(TableIdx, TypeIdx),
1112}
1113
1114#[derive(Debug, Clone)]
1115pub enum ImportOrFunc<Expr: 'static> {
1116    Import(Mrc<Import>),
1117    Func(Func<Expr>),
1118}
1119
1120type CoreSectionCache<T, Ast> = SectionCache<T, CoreIndexSpace, CoreSectionType, CoreSection<Ast>>;
1121type CoreSectionIndex<Ast> = SectionIndex<CoreIndexSpace, CoreSectionType, CoreSection<Ast>>;
1122
1123/// The top-level AST node representing a core WASM module
1124///
1125/// Some parts of the AST are customizable by the `Ast` type parameter. See [AstCustomization] for more details.
1126pub struct Module<Ast: AstCustomization + 'static> {
1127    sections: Sections<CoreIndexSpace, CoreSectionType, CoreSection<Ast>>,
1128
1129    types: CoreSectionCache<FuncType, Ast>,
1130    func_type_refs: CoreSectionCache<FuncTypeRef, Ast>,
1131    codes: CoreSectionCache<FuncCode<Ast::Expr>, Ast>,
1132    tables: CoreSectionCache<Table, Ast>,
1133    mems: CoreSectionCache<Mem, Ast>,
1134    globals: CoreSectionCache<Global, Ast>,
1135    elems: CoreSectionCache<Elem<Ast::Expr>, Ast>,
1136    datas: CoreSectionCache<Ast::Data, Ast>,
1137    start: CoreSectionCache<Start, Ast>,
1138    imports: CoreSectionCache<Import, Ast>,
1139    exports: CoreSectionCache<Export, Ast>,
1140    customs: CoreSectionCache<Ast::Custom, Ast>,
1141
1142    type_index: CoreSectionIndex<Ast>,
1143    func_index: CoreSectionIndex<Ast>,
1144    code_index: CoreSectionIndex<Ast>,
1145    table_index: CoreSectionIndex<Ast>,
1146    mem_index: CoreSectionIndex<Ast>,
1147    global_index: CoreSectionIndex<Ast>,
1148    elem_index: CoreSectionIndex<Ast>,
1149    data_index: CoreSectionIndex<Ast>,
1150    export_index: CoreSectionIndex<Ast>,
1151}
1152
1153#[cfg(feature = "parser")]
1154impl<Ast> Module<Ast>
1155where
1156    Ast: AstCustomization + 'static,
1157    Ast::Expr: TryFromExprSource,
1158    Ast::Data: From<Data<Ast::Expr>>,
1159    Ast::Custom: From<Custom>,
1160{
1161    /// Parses a module from a binary WASM byte array
1162    pub fn from_bytes(bytes: &[u8]) -> Result<Self, String> {
1163        let parser = wasmparser::Parser::new(0);
1164        Self::try_from((parser, bytes))
1165    }
1166}
1167
1168#[cfg(feature = "writer")]
1169impl<Ast> Module<Ast>
1170where
1171    Ast: AstCustomization + 'static,
1172    Ast::Expr: RetainsInstructions,
1173    Ast::Data: Into<Data<Ast::Expr>>,
1174    Ast::Custom: Into<Custom>,
1175{
1176    /// Serializes the module into a binary WASM byte array
1177    pub fn into_bytes(self) -> Result<Vec<u8>, String> {
1178        let encoder: wasm_encoder::Module = self.try_into()?;
1179        Ok(encoder.finish())
1180    }
1181}
1182
1183impl<Ast: AstCustomization> Module<Ast> {
1184    /// Creates an empty module
1185    pub fn empty() -> Self {
1186        Self::new(Sections::new())
1187    }
1188
1189    pub(crate) fn new(
1190        sections: Sections<CoreIndexSpace, CoreSectionType, CoreSection<Ast>>,
1191    ) -> Self {
1192        Self {
1193            sections,
1194            types: new_core_section_cache!(Type),
1195            func_type_refs: new_core_section_cache!(Func),
1196            codes: new_core_section_cache!(Code),
1197            tables: new_core_section_cache!(Table),
1198            mems: new_core_section_cache!(Mem),
1199            globals: new_core_section_cache!(Global),
1200            elems: new_core_section_cache!(Elem),
1201            datas: new_core_section_cache!(Data),
1202            start: new_core_section_cache!(Start),
1203            imports: new_core_section_cache!(Import),
1204            exports: new_core_section_cache!(Export),
1205            customs: new_core_section_cache!(Custom),
1206            type_index: SectionIndex::new(CoreIndexSpace::Type),
1207            func_index: SectionIndex::new(CoreIndexSpace::Func),
1208            code_index: SectionIndex::new(CoreIndexSpace::Code),
1209            table_index: SectionIndex::new(CoreIndexSpace::Table),
1210            mem_index: SectionIndex::new(CoreIndexSpace::Mem),
1211            global_index: SectionIndex::new(CoreIndexSpace::Global),
1212            elem_index: SectionIndex::new(CoreIndexSpace::Elem),
1213            data_index: SectionIndex::new(CoreIndexSpace::Data),
1214            export_index: SectionIndex::new(CoreIndexSpace::Export),
1215        }
1216    }
1217
1218    /// Gets all the function types in the module
1219    pub fn types(&self) -> Vec<Mrc<FuncType>> {
1220        self.types.populate(&self.sections);
1221        self.types.all()
1222    }
1223
1224    /// Gets all the function type references in the module
1225    ///
1226    /// A more useful function is [funcs] that combines this and [codes] together.
1227    pub fn func_type_refs(&self) -> Vec<Mrc<FuncTypeRef>> {
1228        self.func_type_refs.populate(&self.sections);
1229        self.func_type_refs.all()
1230    }
1231
1232    /// Gets all the function codes in the module.
1233    ///
1234    /// A more useful function is [funcs] that combines this and [codes] together.
1235    pub fn codes(&self) -> Vec<Mrc<FuncCode<Ast::Expr>>> {
1236        self.codes.populate(&self.sections);
1237        self.codes.all()
1238    }
1239
1240    /// Gets all the functions defined in the module
1241    pub fn funcs(&self) -> Vec<Func<Ast::Expr>> {
1242        self.func_type_refs()
1243            .into_iter()
1244            .zip(self.codes())
1245            .map(|(func_type, code)| Func {
1246                type_idx: func_type.type_idx,
1247                code,
1248            })
1249            .collect()
1250    }
1251
1252    /// Gets all the tables defined in the module
1253    pub fn tables(&self) -> Vec<Mrc<Table>> {
1254        self.tables.populate(&self.sections);
1255        self.tables.all()
1256    }
1257
1258    /// Gets all the memories defined in the module
1259    pub fn mems(&self) -> Vec<Mrc<Mem>> {
1260        self.mems.populate(&self.sections);
1261        self.mems.all()
1262    }
1263
1264    /// Gets all the globals defined in the module
1265    pub fn globals(&self) -> Vec<Mrc<Global>> {
1266        self.globals.populate(&self.sections);
1267        self.globals.all()
1268    }
1269
1270    /// Gets all the elems defined in the module
1271    pub fn elems(&self) -> Vec<Mrc<Elem<Ast::Expr>>> {
1272        self.elems.populate(&self.sections);
1273        self.elems.all()
1274    }
1275
1276    /// Gets all the data sections defined in the module
1277    pub fn datas(&self) -> Vec<Mrc<Ast::Data>> {
1278        self.datas.populate(&self.sections);
1279        self.datas.all()
1280    }
1281
1282    /// Gets the start section of the module
1283    pub fn start(&self) -> Option<Mrc<Start>> {
1284        self.start.populate(&self.sections);
1285        self.start.all().pop()
1286    }
1287
1288    /// Gets all the imports of the module
1289    pub fn imports(&self) -> Vec<Mrc<Import>> {
1290        self.imports.populate(&self.sections);
1291        self.imports.all()
1292    }
1293
1294    /// Gets all the exports of the module
1295    pub fn exports(&self) -> Vec<Mrc<Export>> {
1296        self.exports.populate(&self.sections);
1297        self.exports.all()
1298    }
1299
1300    /// Gets all the custom sections of the module
1301    pub fn customs(&self) -> Vec<Mrc<Ast::Custom>> {
1302        self.customs.populate(&self.sections);
1303        self.customs.all()
1304    }
1305
1306    /// Adds a new data section
1307    pub fn add_data(&mut self, data: Ast::Data) {
1308        self.datas.invalidate();
1309        self.data_index.invalidate();
1310        self.sections.add_to_last_group(CoreSection::Data(data));
1311        self.datas.populate(&self.sections);
1312        let count = self.datas.count();
1313        self.sections.clear_group(&CoreSectionType::DataCount);
1314        self.sections
1315            .add_to_last_group(CoreSection::DataCount(DataCount {
1316                count: (count + 1) as u32,
1317            }));
1318    }
1319
1320    /// Adds a new elem
1321    pub fn add_elem(&mut self, elem: Elem<Ast::Expr>) {
1322        self.elems.invalidate();
1323        self.elem_index.invalidate();
1324        self.sections.add_to_last_group(CoreSection::Elem(elem));
1325    }
1326
1327    /// Adds a new export
1328    pub fn add_export(&mut self, export: Export) {
1329        self.exports.invalidate();
1330        self.export_index.invalidate();
1331        self.sections.add_to_last_group(CoreSection::Export(export));
1332    }
1333
1334    /// Adds a new function
1335    pub fn add_function(
1336        &mut self,
1337        func_type: FuncType,
1338        locals: Vec<ValType>,
1339        body: Ast::Expr,
1340    ) -> FuncIdx {
1341        let existing_type_idx = self.type_idx_of(&func_type);
1342        let type_idx = match existing_type_idx {
1343            Some(idx) => idx as TypeIdx,
1344            None => {
1345                let idx = self.types.count() as TypeIdx;
1346                self.types.invalidate();
1347                self.type_index.invalidate();
1348                self.sections
1349                    .add_to_last_group(CoreSection::Type(func_type));
1350                idx
1351            }
1352        };
1353        let func_type_ref = FuncTypeRef { type_idx };
1354        let func_code = FuncCode { locals, body };
1355        self.codes.invalidate();
1356        self.code_index.invalidate();
1357        self.func_type_refs.invalidate();
1358        self.func_index.invalidate();
1359        self.sections
1360            .add_to_last_group(CoreSection::Func(func_type_ref));
1361        self.sections
1362            .add_to_last_group(CoreSection::Code(func_code));
1363        self.func_type_refs.populate(&self.sections);
1364        (self.func_type_refs.count() - 1) as FuncIdx
1365    }
1366
1367    /// Adds a new global
1368    pub fn add_global(&mut self, global: Global) {
1369        self.globals.invalidate();
1370        self.global_index.invalidate();
1371        self.sections.add_to_last_group(CoreSection::Global(global));
1372    }
1373
1374    /// Adds a new memory
1375    pub fn add_memory(&mut self, mem: Mem) {
1376        self.mems.invalidate();
1377        self.mem_index.invalidate();
1378        self.sections.add_to_last_group(CoreSection::Mem(mem));
1379    }
1380
1381    /// Adds a new table
1382    pub fn add_table(&mut self, table: Table) {
1383        self.tables.invalidate();
1384        self.sections.add_to_last_group(CoreSection::Table(table));
1385    }
1386
1387    /// Adds a new function type
1388    pub fn add_type(&mut self, func_type: FuncType) {
1389        self.types.invalidate();
1390        self.type_index.invalidate();
1391        self.sections
1392            .add_to_last_group(CoreSection::Type(func_type));
1393    }
1394
1395    /// Gets a function body by its index
1396    pub fn get_code(&mut self, func_idx: FuncIdx) -> Option<Mrc<FuncCode<Ast::Expr>>> {
1397        self.code_index.populate(&self.sections);
1398        match self.code_index.get(&func_idx) {
1399            Some(section) => match &*section {
1400                CoreSection::Code(_) => Some(Mrc::map(section, |section| section.as_code())),
1401                _ => None,
1402            },
1403            None => None,
1404        }
1405    }
1406
1407    /// Gets a data section by its index
1408    pub fn get_data(&mut self, data_idx: DataIdx) -> Option<Mrc<Ast::Data>> {
1409        self.data_index.populate(&self.sections);
1410        match self.data_index.get(&data_idx) {
1411            Some(section) => match &*section {
1412                CoreSection::Data(_) => Some(Mrc::map(section, |section| section.as_data())),
1413                _ => None,
1414            },
1415            _ => None,
1416        }
1417    }
1418
1419    /// Gets an elem by its index
1420    pub fn get_elem(&mut self, elem_idx: ElemIdx) -> Option<Mrc<Elem<Ast::Expr>>> {
1421        self.elem_index.populate(&self.sections);
1422        match self.elem_index.get(&elem_idx) {
1423            Some(section) => match &*section {
1424                CoreSection::Elem(_) => Some(Mrc::map(section, |section| section.as_elem())),
1425                _ => None,
1426            },
1427            _ => None,
1428        }
1429    }
1430
1431    /// Gets an export by its index
1432    pub fn get_export(&mut self, export_idx: ExportIdx) -> Option<Mrc<Export>> {
1433        self.export_index.populate(&self.sections);
1434        match self.export_index.get(&export_idx) {
1435            Some(section) => match &*section {
1436                CoreSection::Export(_) => Some(Mrc::map(section, |section| section.as_export())),
1437                _ => None,
1438            },
1439            _ => None,
1440        }
1441    }
1442
1443    /// Gets a function by its index
1444    ///
1445    /// In a core WASM module the function index space holds both defined functions and imported functions.
1446    pub fn get_function(&mut self, func_idx: FuncIdx) -> Option<ImportOrFunc<Ast::Expr>> {
1447        self.func_index.populate(&self.sections);
1448        match self.func_index.get(&func_idx) {
1449            Some(section) => match &*section {
1450                CoreSection::Func(_) => {
1451                    let code = self.get_code(func_idx).unwrap();
1452                    let func_type_ref = section.as_func();
1453                    let func = Func {
1454                        type_idx: func_type_ref.type_idx,
1455                        code,
1456                    };
1457                    Some(ImportOrFunc::Func(func))
1458                }
1459                CoreSection::Import(_) => {
1460                    Some(ImportOrFunc::Import(Mrc::map(section, |section| {
1461                        section.as_import()
1462                    })))
1463                }
1464                _ => None,
1465            },
1466            _ => None,
1467        }
1468    }
1469
1470    /// Gets a global by its index
1471    pub fn get_global(&mut self, global_idx: GlobalIdx) -> Option<Mrc<Global>> {
1472        self.global_index.populate(&self.sections);
1473        match self.global_index.get(&global_idx) {
1474            Some(section) => match &*section {
1475                CoreSection::Global(_) => Some(Mrc::map(section, |section| section.as_global())),
1476                _ => None,
1477            },
1478            _ => None,
1479        }
1480    }
1481
1482    /// Gets a memory by its index
1483    pub fn get_memory(&mut self, mem_idx: MemIdx) -> Option<Mrc<Mem>> {
1484        self.mem_index.populate(&self.sections);
1485        match self.mem_index.get(&mem_idx) {
1486            Some(section) => match &*section {
1487                CoreSection::Mem(_) => Some(Mrc::map(section, |section| section.as_mem())),
1488                _ => None,
1489            },
1490            _ => None,
1491        }
1492    }
1493
1494    /// Gets a table by its index
1495    pub fn get_table(&mut self, table_idx: TableIdx) -> Option<Mrc<Table>> {
1496        self.table_index.populate(&self.sections);
1497        match self.table_index.get(&table_idx) {
1498            Some(section) => match &*section {
1499                CoreSection::Table(_) => Some(Mrc::map(section, |section| section.as_table())),
1500                _ => None,
1501            },
1502            _ => None,
1503        }
1504    }
1505
1506    /// Checks whether a given function type is already defined in the module, and returs its type index if so.
1507    pub fn type_idx_of(&self, func_type: &FuncType) -> Option<TypeIdx> {
1508        self.types.populate(&self.sections);
1509        self.types
1510            .all()
1511            .into_iter()
1512            .position(|ft| *ft == *func_type)
1513            .map(|idx| idx as TypeIdx)
1514    }
1515
1516    /// Converts the module into a sequence of sections
1517    pub fn into_sections(mut self) -> Vec<Mrc<CoreSection<Ast>>> {
1518        self.sections.take_all()
1519    }
1520
1521    /// Converts the module into a grouped sequence of sections, exactly as it should be written to a binary WASM file
1522    pub fn into_grouped(self) -> Vec<(CoreSectionType, Vec<Mrc<CoreSection<Ast>>>)> {
1523        self.sections.into_grouped()
1524    }
1525}
1526
1527impl<Ast> Module<Ast>
1528where
1529    Ast: AstCustomization,
1530    Ast::Custom: RetainsCustomSection,
1531{
1532    /// Gets all the metadata supported by the `wasm-metadata` crate defined in this module's custom sections
1533    #[cfg(feature = "metadata")]
1534    pub fn get_metadata(&self) -> Option<metadata::Metadata> {
1535        let mut producers = None;
1536        let mut name = None;
1537
1538        for custom in self.customs() {
1539            if custom.name() == "producers" {
1540                producers = wasm_metadata::Producers::from_bytes(custom.data(), 0).ok();
1541            } else if custom.name() == "name" {
1542                name = wasm_metadata::ModuleNames::from_bytes(custom.data(), 0)
1543                    .ok()
1544                    .and_then(|n| n.get_name().cloned());
1545            }
1546        }
1547
1548        if producers.is_some() || name.is_some() {
1549            Some(metadata::Metadata {
1550                name,
1551                producers: producers.map(|p| p.into()),
1552            })
1553        } else {
1554            None
1555        }
1556    }
1557}
1558
1559impl<Ast: AstCustomization> Debug for Module<Ast> {
1560    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1561        self.sections.fmt(f)
1562    }
1563}
1564
1565impl<Ast: AstCustomization> PartialEq for Module<Ast> {
1566    fn eq(&self, other: &Self) -> bool {
1567        self.sections.eq(&other.sections)
1568    }
1569}
1570
1571impl<Ast: AstCustomization> From<Sections<CoreIndexSpace, CoreSectionType, CoreSection<Ast>>>
1572    for Module<Ast>
1573{
1574    fn from(value: Sections<CoreIndexSpace, CoreSectionType, CoreSection<Ast>>) -> Self {
1575        Self::new(value)
1576    }
1577}
1578
1579impl<Ast: AstCustomization> Clone for Module<Ast> {
1580    fn clone(&self) -> Self {
1581        Module::from(self.sections.clone())
1582    }
1583}
1584
1585#[cfg(feature = "component")]
1586impl<Ast: AstCustomization>
1587    Section<crate::component::ComponentIndexSpace, crate::component::ComponentSectionType>
1588    for Module<Ast>
1589{
1590    fn index_space(&self) -> crate::component::ComponentIndexSpace {
1591        crate::component::ComponentIndexSpace::Module
1592    }
1593
1594    fn section_type(&self) -> crate::component::ComponentSectionType {
1595        crate::component::ComponentSectionType::Module
1596    }
1597}