wasm_ast/model/module.rs
1//! WebAssembly model of modules and their segments.
2
3use crate::model::indices::*;
4use crate::model::types::*;
5use crate::model::{Expression, Name};
6use crate::{ModelError, ReferenceInstruction};
7use std::collections::HashMap;
8use std::convert::TryFrom;
9use std::mem::discriminant;
10
11/// A builder pattern for `Module`s.
12/// The builder performs minimal validation when using the `add_*` family of methods.
13/// The builder validates that the added element would not exceed the maximum size of a u32.
14/// No other validations are performed.
15pub struct ModuleBuilder {
16    module: Module,
17}
18
19impl ModuleBuilder {
20    /// Creates a new empty builder of WebAssembly modules.
21    pub fn new() -> Self {
22        ModuleBuilder {
23            module: Module::empty(),
24        }
25    }
26
27    /// Sets the function types segment for the WebAssembly module to be built.
28    pub fn set_function_types(&mut self, function_types: Option<Vec<FunctionType>>) {
29        self.module.function_types = function_types;
30    }
31
32    /// Adds the function type to the module's segment.
33    /// Returns the index of the type in the module.
34    pub fn add_function_type(
35        &mut self,
36        function_type: FunctionType,
37    ) -> Result<TypeIndex, ModelError> {
38        let function_types = self.module.function_types.get_or_insert_with(Vec::new);
39        let index = u32::try_from(function_types.len())?;
40
41        function_types.push(function_type);
42
43        Ok(index)
44    }
45
46    /// Sets the functions segment for the WebAssembly module to be built.
47    pub fn set_functions(&mut self, functions: Option<Vec<Function>>) {
48        self.module.functions = functions;
49    }
50
51    /// Adds the function to the module's segment.
52    /// Returns the index of the function in the module.
53    ///
54    /// **Note:** In order for the returned index to be accurate,
55    /// all function imports must be defined prior to adding any functions.
56    pub fn add_function(&mut self, function: Function) -> Result<FunctionIndex, ModelError> {
57        let functions = self.module.functions.get_or_insert_with(Vec::new);
58        let imports = match &self.module.imports {
59            Some(imports) => imports
60                .iter()
61                .filter(|import| matches!(import.description(), ImportDescription::Function(_)))
62                .count(),
63            None => 0,
64        };
65        let index = u32::try_from(functions.len() + imports)?;
66
67        functions.push(function);
68
69        Ok(index)
70    }
71
72    /// Sets the table segment for the WebAssembly module to be built.
73    pub fn set_tables(&mut self, tables: Option<Vec<Table>>) {
74        self.module.tables = tables;
75    }
76
77    /// Adds the table to the module's segment.
78    /// Returns the index of the table in the module.
79    ///
80    /// **Note:** In order for the returned index to be accurate,
81    /// all table imports must be defined prior to adding any tables.
82    pub fn add_table(&mut self, table: Table) -> Result<TableIndex, ModelError> {
83        let tables = self.module.tables.get_or_insert_with(Vec::new);
84        let imports = match &self.module.imports {
85            Some(imports) => imports
86                .iter()
87                .filter(|import| matches!(import.description(), ImportDescription::Table(_)))
88                .count(),
89            None => 0,
90        };
91        let index = u32::try_from(tables.len() + imports)?;
92
93        tables.push(table);
94
95        Ok(index)
96    }
97
98    /// Sets the tables segment for the WebAssembly module to be built.
99    pub fn set_memories(&mut self, memories: Option<Vec<Memory>>) {
100        self.module.memories = memories;
101    }
102
103    /// Adds the memory to the module's segment.
104    /// Returns the index of the memory in the module.
105    ///
106    /// **Note:** In order for the returned index to be accurate,
107    /// all memory imports must be defined prior to adding any memories.
108    pub fn add_memory(&mut self, memory: Memory) -> Result<MemoryIndex, ModelError> {
109        let memories = self.module.memories.get_or_insert_with(Vec::new);
110        let imports = match &self.module.imports {
111            Some(imports) => imports
112                .iter()
113                .filter(|import| matches!(import.description(), ImportDescription::Memory(_)))
114                .count(),
115            None => 0,
116        };
117        let index = u32::try_from(memories.len() + imports)?;
118
119        memories.push(memory);
120
121        Ok(index)
122    }
123
124    /// Sets the globals segment for the WebAssembly module to be built.
125    pub fn set_globals(&mut self, globals: Option<Vec<Global>>) {
126        self.module.globals = globals;
127    }
128
129    /// Adds the global to the module's segment.
130    /// Returns the index of the global in the module.
131    ///
132    /// **Note:** In order for the returned index to be accurate,
133    /// all global imports must be defined prior to adding any globals.
134    pub fn add_global(&mut self, global: Global) -> Result<GlobalIndex, ModelError> {
135        let globals = self.module.globals.get_or_insert_with(Vec::new);
136        let imports = match &self.module.imports {
137            Some(imports) => imports
138                .iter()
139                .filter(|import| matches!(import.description(), ImportDescription::Global(_)))
140                .count(),
141            None => 0,
142        };
143        let index = u32::try_from(globals.len() + imports)?;
144
145        globals.push(global);
146
147        Ok(index)
148    }
149
150    /// Sets the elements segment for the WebAssembly module to be built.
151    pub fn set_elements(&mut self, elements: Option<Vec<Element>>) {
152        self.module.elements = elements;
153    }
154
155    /// Adds the element to the module's segment.
156    /// Returns the index of the element in the module.
157    pub fn add_element(&mut self, element: Element) -> Result<ElementIndex, ModelError> {
158        let elements = self.module.elements.get_or_insert_with(Vec::new);
159        let index = u32::try_from(elements.len())?;
160
161        elements.push(element);
162
163        Ok(index)
164    }
165
166    /// Sets the data segment for the WebAssembly module to be built.
167    pub fn set_data(&mut self, data: Option<Vec<Data>>) {
168        self.module.data = data;
169    }
170
171    /// Adds the data to the module's segment.
172    /// Returns the index of the data in the module.
173    pub fn add_data(&mut self, datum: Data) -> Result<DataIndex, ModelError> {
174        let data = self.module.data.get_or_insert_with(Vec::new);
175        let index = u32::try_from(data.len())?;
176
177        data.push(datum);
178
179        Ok(index)
180    }
181
182    /// Sets the start segment for the WebAssembly module to be built.
183    pub fn set_start(&mut self, start: Option<Start>) {
184        self.module.start = start;
185    }
186
187    /// Sets the imports segment for the WebAssembly module to be built.
188    pub fn set_imports(&mut self, imports: Option<Vec<Import>>) {
189        self.module.imports = imports;
190    }
191
192    /// Adds the import to the module's segment.
193    /// Returns the index of the import in the module (i.e function, table, memory, or global index).
194    pub fn add_import(&mut self, import: Import) -> Result<u32, ModelError> {
195        let import_discriminant = discriminant(import.description());
196        let imports = self.module.imports.get_or_insert_with(Vec::new);
197        let index = u32::try_from(
198            imports
199                .iter()
200                .filter(|i| discriminant(i.description()) == import_discriminant)
201                .count(),
202        )?;
203
204        imports.push(import);
205
206        Ok(index)
207    }
208
209    /// Sets the exports segment for the WebAssembly module to be built.
210    pub fn set_exports(&mut self, exports: Option<Vec<Export>>) {
211        self.module.exports = exports;
212    }
213
214    /// Adds the export to the module's segment.
215    /// Returns the index of the export in the module.
216    pub fn add_export(&mut self, export: Export) {
217        let exports = self.module.exports.get_or_insert_with(Vec::new);
218        exports.push(export);
219    }
220
221    /// Sets the custom section at the given insertion point for the WebAssembly module to be built.
222    /// WebAssembly binary format allows custom sections to be at the start of a module, or after any other section.
223    pub fn set_custom_sections(
224        &mut self,
225        insertion_point: ModuleSection,
226        custom_sections: Option<Vec<Custom>>,
227    ) {
228        self.module
229            .custom_sections
230            .set_custom_sections(insertion_point, custom_sections);
231    }
232
233    /// Adds the export to the module's segment.
234    /// Returns the index of the export in the module.
235    pub fn add_custom_section(&mut self, insertion_point: ModuleSection, custom_section: Custom) {
236        self.module
237            .custom_sections
238            .add_custom_section(insertion_point, custom_section);
239    }
240
241    /// Determines whether the WebAssembly module to be built will include a data count section or not.  
242    pub fn set_data_count(&mut self, data_count: Option<u32>) {
243        self.module.data_count = data_count;
244    }
245
246    /// Includes a data count based on the number of data segments currently in this builder.
247    pub fn include_data_count(&mut self) {
248        self.module.data_count = self.module.data.as_ref().map(|v| v.len()).map(|l| l as u32);
249    }
250
251    /// The ππππΎπ component of the module to be built.
252    pub fn function_types(&self) -> Option<&[FunctionType]> {
253        self.module.function_types()
254    }
255
256    /// The πΏπππΌπ component of the module to be built.
257    pub fn functions(&self) -> Option<&[Function]> {
258        self.module.functions()
259    }
260
261    /// The ππΊπ»π
πΎπ component of the module to be built.
262    pub fn tables(&self) -> Option<&[Table]> {
263        self.module.tables()
264    }
265
266    /// The ππΎππ component of the module to be built.
267    pub fn memories(&self) -> Option<&[Memory]> {
268        self.module.memories()
269    }
270
271    /// The ππ
ππ»πΊπ
π component of the module to be built.
272    pub fn globals(&self) -> Option<&[Global]> {
273        self.module.globals()
274    }
275
276    /// The πΎπ
πΎππ component of the module to be built.
277    pub fn elements(&self) -> Option<&[Element]> {
278        self.module.elements()
279    }
280
281    /// The π½πΊππΊπ component of the module to be built.
282    pub fn data(&self) -> Option<&[Data]> {
283        self.module.data()
284    }
285
286    /// The πππΊππ component of the module to be built.
287    pub fn start(&self) -> Option<&Start> {
288        self.module.start()
289    }
290
291    /// The πππππππ component of the module to be built.
292    pub fn imports(&self) -> Option<&[Import]> {
293        self.module.imports()
294    }
295
296    /// The πΎππππππ component of the module to be built.
297    pub fn exports(&self) -> Option<&[Export]> {
298        self.module.exports()
299    }
300
301    /// The custom sections of the module to be built.
302    pub fn custom_sections_at(&self, insertion_point: ModuleSection) -> Option<&[Custom]> {
303        self.module.custom_sections_at(insertion_point)
304    }
305
306    /// Builds the current segments into a module.
307    pub fn build(self) -> Module {
308        self.into()
309    }
310}
311
312impl From<ModuleBuilder> for Module {
313    fn from(builder: ModuleBuilder) -> Self {
314        builder.module
315    }
316}
317
318impl Default for ModuleBuilder {
319    fn default() -> Self {
320        ModuleBuilder {
321            module: Module::empty(),
322        }
323    }
324}
325
326/// WebAssembly programs are organized into modules, which are the unit of deployment, loading, and compilation.
327/// A module collects definitions for types, functions, tables, memories, and globals.
328/// In addition,
329/// it can declare imports and exports and provide initialization in the form of data and element segments,
330/// or a start function.
331/// Each of the vectors β and thus the entire module β may be empty.
332///
333/// See <https://webassembly.github.io/spec/core/syntax/modules.html#modules>
334///
335/// # Examples
336/// ## Empty
337/// ```rust
338/// use wasm_ast::{Module, ModuleSection};
339///
340/// let module = Module::empty();
341///
342/// assert_eq!(module.functions(), None);
343/// assert_eq!(module.functions(), None);
344/// assert_eq!(module.tables(), None);
345/// assert_eq!(module.memories(), None);
346/// assert_eq!(module.globals(), None);
347/// assert_eq!(module.elements(), None);
348/// assert_eq!(module.data(), None);
349/// assert_eq!(module.start(), None);
350/// assert_eq!(module.imports(), None);
351/// assert_eq!(module.exports(), None);
352/// assert_eq!(module.data_count(), None);
353/// ```
354///
355/// ## Builder
356/// ```rust
357/// use wasm_ast::{Module, Import, FunctionType, ValueType, Start, Function, ResultType, ControlInstruction, Memory, Limit, Export, Data, Expression, ModuleSection, Custom};
358///
359/// let mut module = Module::builder();
360/// let module = module.build();
361///
362/// assert_eq!(module.functions(), None);
363/// assert_eq!(module.functions(), None);
364/// assert_eq!(module.tables(), None);
365/// assert_eq!(module.memories(), None);
366/// assert_eq!(module.globals(), None);
367/// assert_eq!(module.elements(), None);
368/// assert_eq!(module.data(), None);
369/// assert_eq!(module.start(), None);
370/// assert_eq!(module.imports(), None);
371/// assert_eq!(module.exports(), None);
372/// assert_eq!(module.data_count(), None);
373/// ```
374#[derive(Clone, Debug, PartialEq)]
375pub struct Module {
376    function_types: Option<Vec<FunctionType>>,
377    functions: Option<Vec<Function>>,
378    tables: Option<Vec<Table>>,
379    memories: Option<Vec<Memory>>,
380    globals: Option<Vec<Global>>,
381    elements: Option<Vec<Element>>,
382    data: Option<Vec<Data>>,
383    start: Option<Start>,
384    imports: Option<Vec<Import>>,
385    exports: Option<Vec<Export>>,
386    custom_sections: CustomSections,
387    data_count: Option<u32>,
388}
389
390impl Module {
391    /// Creates a builder for WebAssembly modules.
392    pub fn builder() -> ModuleBuilder {
393        ModuleBuilder::new()
394    }
395
396    /// Creates a new empty `Module`.
397    pub fn empty() -> Self {
398        Module {
399            function_types: None,
400            functions: None,
401            tables: None,
402            memories: None,
403            globals: None,
404            elements: None,
405            data: None,
406            start: None,
407            imports: None,
408            exports: None,
409            custom_sections: CustomSections::new(),
410            data_count: None,
411        }
412    }
413
414    /// The ππππΎπ component of a module defines a vector of function types.
415    pub fn function_types(&self) -> Option<&[FunctionType]> {
416        self.function_types.as_deref()
417    }
418
419    /// The πΏπππΌπ component of a module defines a vector of functions.
420    pub fn functions(&self) -> Option<&[Function]> {
421        self.functions.as_deref()
422    }
423
424    /// The ππΊπ»π
πΎπ component of a module defines a vector of tables described by their table type.
425    pub fn tables(&self) -> Option<&[Table]> {
426        self.tables.as_deref()
427    }
428
429    /// The ππΎππ component of a module defines a vector of linear memories (or memories for short)
430    /// as described by their memory type.
431    pub fn memories(&self) -> Option<&[Memory]> {
432        self.memories.as_deref()
433    }
434
435    /// The ππ
ππ»πΊπ
π component of a module defines a vector of global variables (or globals for short).
436    pub fn globals(&self) -> Option<&[Global]> {
437        self.globals.as_deref()
438    }
439
440    /// The πΎπ
πΎππ component of a module defines a vector of element segments.
441    pub fn elements(&self) -> Option<&[Element]> {
442        self.elements.as_deref()
443    }
444
445    /// The π½πΊππΊπ component of a module defines a vector of data segments.
446    pub fn data(&self) -> Option<&[Data]> {
447        self.data.as_deref()
448    }
449
450    /// The πππΊππ component of a module declares the function index of a start function that is
451    /// automatically invoked when the module is instantiated, after tables and memories have been initialized.
452    pub fn start(&self) -> Option<&Start> {
453        self.start.as_ref()
454    }
455
456    /// The πππππππ component of a module defines a set of imports that are required for instantiation.
457    pub fn imports(&self) -> Option<&[Import]> {
458        self.imports.as_deref()
459    }
460
461    /// The πΎππππππ component of a module defines a set of exports that become accessible to the
462    /// host environment once the module has been instantiated.
463    pub fn exports(&self) -> Option<&[Export]> {
464        self.exports.as_deref()
465    }
466
467    /// The custom sections of a module for a given insertion point.
468    /// Custom sections are allowed at the beginning of a module and after every other section.
469    pub fn custom_sections_at(&self, insertion_point: ModuleSection) -> Option<&[Custom]> {
470        self.custom_sections.custom_sections_at(insertion_point)
471    }
472
473    /// Whether the module includes the data count section or not.
474    pub fn data_count(&self) -> Option<u32> {
475        self.data_count
476    }
477}
478
479/// Maps insertion points to custom sections for a WebAssembly module.
480#[derive(Clone, Debug)]
481struct CustomSections {
482    custom_sections: HashMap<ModuleSection, Vec<Custom>>,
483}
484
485impl CustomSections {
486    /// Creates a new empty instance of custom sections.
487    pub fn new() -> Self {
488        CustomSections {
489            custom_sections: HashMap::new(),
490        }
491    }
492
493    /// The custom sections of the module to be built.
494    pub fn custom_sections_at(&self, insertion_point: ModuleSection) -> Option<&[Custom]> {
495        self.custom_sections
496            .get(&insertion_point)
497            .map(Vec::as_slice)
498    }
499
500    /// Sets the custom section at the given insertion point for the WebAssembly module to be built.
501    /// WebAssembly binary format allows custom sections to be at the start of a module, or after any other section.
502    pub fn set_custom_sections(
503        &mut self,
504        insertion_point: ModuleSection,
505        custom_sections: Option<Vec<Custom>>,
506    ) {
507        match custom_sections {
508            Some(sections) => self.custom_sections.insert(insertion_point, sections),
509            None => self.custom_sections.remove(&insertion_point),
510        };
511    }
512
513    /// Adds the export to the module's segment.
514    /// Returns the index of the export in the module.
515    pub fn add_custom_section(&mut self, insertion_point: ModuleSection, custom_section: Custom) {
516        let custom_sections = self
517            .custom_sections
518            .entry(insertion_point)
519            .or_insert_with(Vec::new);
520
521        custom_sections.push(custom_section);
522    }
523}
524
525impl PartialEq for CustomSections {
526    fn eq(&self, other: &Self) -> bool {
527        self.custom_sections.len() == other.custom_sections.len()
528            && self.custom_sections.keys().all(|key| {
529                other.custom_sections.contains_key(key)
530                    && self.custom_sections.get(key) == other.custom_sections.get(key)
531            })
532    }
533}
534
535/// Custom sections have the id 0.
536/// They are intended to be used for debugging information or third-party extensions,
537/// and are ignored by the WebAssembly semantics. Their contents consist of a name further
538/// identifying the custom section, followed by an uninterpreted sequence of bytes for custom use.
539///
540/// See <https://webassembly.github.io/spec/core/binary/modules.html#binary-customsec>
541///
542/// # Examples
543/// ```rust
544/// use wasm_ast::{Custom, Name};
545///
546/// let name = "version";
547/// let version = b"1.0.0";
548/// let custom = Custom::new(name.into(), version.to_vec());
549///
550/// assert_eq!(custom.name(), &Name::new(name.to_string()));
551/// assert_eq!(custom.bytes(), &version[..]);
552/// ```
553#[derive(Clone, Debug, PartialEq)]
554pub struct Custom {
555    name: Name,
556    bytes: Vec<u8>,
557}
558
559impl Custom {
560    /// Creates a new instance of a custom section.
561    pub fn new(name: Name, bytes: Vec<u8>) -> Self {
562        Custom { name, bytes }
563    }
564
565    /// The name of the custom section.
566    pub fn name(&self) -> &Name {
567        &self.name
568    }
569
570    /// The contents of the custom section.
571    pub fn bytes(&self) -> &[u8] {
572        &self.bytes
573    }
574}
575
576/// The ππππΎ of a function declares its signature by reference to a type defined in the module.
577/// The parameters of the function are referenced through 0-based local indices in the functionβs body; they are mutable.
578/// The π
ππΌπΊπ
π declare a vector of mutable local variables and their types.
579/// These variables are referenced through local indices in the functionβs body.
580/// The index of the first local is the smallest index not referencing a parameter.
581/// The π»ππ½π is an instruction sequence that upon termination must produce a stack matching the function typeβs result type.
582///
583/// See <https://webassembly.github.io/spec/core/syntax/modules.html#functions>
584///
585/// # Examples
586/// ```rust
587/// use wasm_ast::{Function, TypeIndex, Expression, ResultType, ValueType, NumericInstruction, NumberType};
588///
589/// let locals: ResultType = vec![ValueType::I32, ValueType::F32].into();
590/// let body: Expression = vec![
591///     32u32.into(),
592///     2u32.into(),
593///     NumericInstruction::Multiply(NumberType::I32).into()
594/// ].into();
595/// let function = Function::new(0, locals.clone(), body.clone());
596///
597/// assert_eq!(function.kind(), 0);
598/// assert_eq!(function.locals(), &locals);
599/// assert_eq!(function.body(), &body);
600/// ```
601#[derive(Clone, Debug, PartialEq)]
602pub struct Function {
603    kind: TypeIndex,
604    locals: ResultType,
605    body: Expression,
606}
607
608impl Function {
609    pub fn new(kind: TypeIndex, locals: ResultType, body: Expression) -> Self {
610        Function { kind, locals, body }
611    }
612
613    /// The index of the type definition for this `Function`.
614    pub fn kind(&self) -> TypeIndex {
615        self.kind
616    }
617
618    /// The types of the locals of this `Function`.
619    pub fn locals(&self) -> &ResultType {
620        &self.locals
621    }
622
623    /// The code for this `Function`.
624    pub fn body(&self) -> &Expression {
625        &self.body
626    }
627}
628
629/// A table is a vector of opaque values of a particular reference type.
630/// The πππ size in the limits of the table type specifies the initial size of that table, while its ππΊπ, if present, restricts the size to which it can grow later.
631/// Tables can be initialized through element segments.
632/// Tables are referenced through table indices,
633/// starting with the smallest index not referencing a table import.
634/// Most constructs implicitly reference table index 0.
635///
636/// See <https://webassembly.github.io/spec/core/syntax/modules.html#tables>
637///
638/// # Examples
639/// ```rust
640/// use wasm_ast::{Table, TableType, Limit, ReferenceType};
641///
642/// let limit = Limit::bounded(1, 2);
643/// let kind = TableType::new( ReferenceType::Function,limit);
644/// let table = Table::new(kind);
645///
646/// assert_eq!(table, kind.into());
647/// assert_eq!(table.kind(), &kind);
648/// ```
649#[derive(Copy, Clone, Debug, Eq, PartialEq)]
650pub struct Table {
651    kind: TableType,
652}
653
654impl Table {
655    /// Creates a new instance of a `Table`.
656    pub fn new(kind: TableType) -> Self {
657        Table { kind }
658    }
659
660    /// The type descriptor of this `Table`.
661    pub fn kind(&self) -> &TableType {
662        &self.kind
663    }
664}
665
666impl From<TableType> for Table {
667    fn from(kind: TableType) -> Self {
668        Table { kind }
669    }
670}
671
672/// A memory is a vector of raw uninterpreted bytes.
673/// The πππ size in the limits of the memory type specifies the initial size of that memory,
674/// while its ππΊπ, if present, restricts the size to which it can grow later. Both are in units of page size.
675/// Memories can be initialized through data segments.
676/// Memories are referenced through memory indices
677/// starting with the smallest index not referencing a memory import.
678/// Most constructs implicitly reference memory index 0.
679///
680/// See <https://webassembly.github.io/spec/core/syntax/modules.html#memories>
681///
682/// # Examples
683/// ```rust
684/// use wasm_ast::{Memory, MemoryType, Limit};
685///
686/// let limit = Limit::bounded(1, 2);
687/// let kind = MemoryType::new(limit);
688/// let memory = Memory::new(kind);
689///
690/// assert_eq!(memory, kind.into());
691/// assert_eq!(memory, limit.into());
692/// assert_eq!(memory.kind(), &kind);
693/// ```
694#[derive(Copy, Clone, Debug, Eq, PartialEq)]
695pub struct Memory {
696    kind: MemoryType,
697}
698
699impl Memory {
700    /// Creates a new `Memory` of the given type.
701    pub fn new(kind: MemoryType) -> Self {
702        Memory { kind }
703    }
704
705    /// The type definition for this memory.
706    pub fn kind(&self) -> &MemoryType {
707        &self.kind
708    }
709}
710
711impl<T> From<T> for Memory
712where
713    T: Into<MemoryType>,
714{
715    fn from(kind: T) -> Self {
716        Memory { kind: kind.into() }
717    }
718}
719
720/// Each global stores a single value of the given global type.
721/// Its ππππΎ also specifies whether a global is immutable or mutable.
722/// Moreover, each global is initialized with an ππππ value given by a constant initializer expression.
723/// Globals are referenced through global indices,
724/// starting with the smallest index not referencing a global import.
725///
726/// See <https://webassembly.github.io/spec/core/syntax/modules.html#globals>
727///
728/// # Examples
729/// ## Immutable
730/// ```rust
731/// use wasm_ast::{Global, GlobalType, ValueType, Expression};
732///
733/// let kind = GlobalType::immutable(ValueType::I64);
734/// let initializer: Expression = vec![0i64.into()].into();
735/// let global = Global::immutable(ValueType::I64, initializer.clone());
736///
737/// assert_eq!(global, Global::new(kind.clone(), initializer.clone()));
738/// assert_eq!(global.kind(), &kind);
739/// assert_eq!(global.initializer(), &initializer);
740/// ```
741///
742/// ## Mutable
743/// ```rust
744/// use wasm_ast::{Global, GlobalType, ValueType, Expression};
745///
746/// let kind = GlobalType::mutable(ValueType::I64);
747/// let initializer: Expression = vec![0i64.into()].into();
748/// let global = Global::mutable(ValueType::I64, initializer.clone());
749///
750/// assert_eq!(global, Global::new(kind.clone(), initializer.clone()));
751/// assert_eq!(global.kind(), &kind);
752/// assert_eq!(global.initializer(), &initializer);
753/// ```
754#[derive(Clone, Debug, PartialEq)]
755pub struct Global {
756    kind: GlobalType,
757    initializer: Expression,
758}
759
760impl Global {
761    /// Creates a new `Global` with the given type and initializer.
762    pub fn new(kind: GlobalType, initializer: Expression) -> Self {
763        Global { kind, initializer }
764    }
765
766    /// Creates a new `Global` for a mutable global variable.
767    pub fn mutable(kind: ValueType, initializer: Expression) -> Self {
768        Global {
769            kind: GlobalType::mutable(kind),
770            initializer,
771        }
772    }
773
774    /// Creates a new `Global` for an immutable global variable.
775    pub fn immutable(kind: ValueType, initializer: Expression) -> Self {
776        Global {
777            kind: GlobalType::immutable(kind),
778            initializer,
779        }
780    }
781
782    /// The type of this `Global`.
783    pub fn kind(&self) -> &GlobalType {
784        &self.kind
785    }
786
787    /// The expression to initialize this `Global` with.
788    pub fn initializer(&self) -> &Expression {
789        &self.initializer
790    }
791}
792
793/// The initial contents of a table is uninitialized.
794/// Element segments can be used to initialize a subrange of a table from a static vector of elements.
795/// Each element segment defines a reference type and a corresponding list of constant element expressions.
796/// Element segments have a mode that identifies them as either passive, active, or declarative.
797/// A passive element segmentβs elements can be copied to a table using the ππΊπ»π
πΎ.ππππ instruction.
798/// An active element segment copies its elements into a table during instantiation,
799/// as specified by a table index and a constant expression defining an offset into that table.
800/// A declarative element segment is not available at runtime but merely serves to forward-declare
801/// references that are formed in code with instructions like ππΎπΏ.πΏπππΌ.
802/// The ππΏπΏππΎπ is given by a constant expression.
803/// Element segments are referenced through element indices.
804///
805/// See <https://webassembly.github.io/spec/core/syntax/modules.html#element-segments>
806///
807/// # Examples
808/// ## Active
809/// ```rust
810/// use wasm_ast::{Element, ElementInitializer, ElementMode, TableIndex, FunctionIndex, Expression, ReferenceType};
811///
812/// let offset: Expression = vec![0i32.into()].into();
813/// let initializers = vec![0].to_initializers();
814/// let element = Element::active(0, offset.clone(), ReferenceType::Function, initializers.clone());
815///
816/// assert_eq!(element, Element::new(
817///     ReferenceType::Function,
818///     ElementMode::Active(0, offset.clone()),
819///     initializers.clone()
820/// ));
821/// assert_eq!(element.kind(), ReferenceType::Function);
822/// assert_eq!(element.mode(), &ElementMode::Active(0, offset.clone()));
823/// assert_eq!(element.initializers(), initializers.as_slice());
824/// ```
825///
826/// ## Passive
827/// ```rust
828/// use wasm_ast::{Element, ElementInitializer, ElementMode, TableIndex, Expression, ReferenceType, NumericInstruction};
829///
830/// let initializers = vec![Expression::from(vec![2i32.into()])].to_initializers();
831/// let element = Element::passive(ReferenceType::External, initializers.clone());
832///
833/// assert_eq!(element, Element::new(
834///     ReferenceType::External,
835///     ElementMode::Passive,
836///     initializers.clone()
837/// ));
838/// assert_eq!(element.kind(), ReferenceType::External);
839/// assert_eq!(element.mode(), &ElementMode::Passive);
840/// assert_eq!(element.initializers(), initializers.as_slice());
841/// ```
842///
843/// ## Declarative
844/// ```rust
845/// use wasm_ast::{Element, ElementInitializer, ElementMode, TableIndex, Expression, ReferenceType, NumericInstruction};
846///
847/// let initializer: Vec<Expression> = vec![Expression::from(vec![2i32.into()])].into();
848/// let element = Element::declarative(ReferenceType::External, initializer.clone());
849///
850/// assert_eq!(element, Element::new(
851///     ReferenceType::External,
852///     ElementMode::Declarative,
853///     initializer.clone()
854/// ));
855/// assert_eq!(element.kind(), ReferenceType::External);
856/// assert_eq!(element.mode(), &ElementMode::Declarative);
857/// assert_eq!(element.initializers(), &initializer);
858/// ````
859#[derive(Clone, Debug, PartialEq)]
860pub struct Element {
861    kind: ReferenceType,
862    mode: ElementMode,
863    initializers: Vec<Expression>,
864}
865
866impl Element {
867    /// Creates a new instance of an element segment.
868    pub fn new(kind: ReferenceType, mode: ElementMode, initializers: Vec<Expression>) -> Self {
869        Element {
870            kind,
871            mode,
872            initializers,
873        }
874    }
875
876    /// Creates a passive element segment.
877    pub fn passive(kind: ReferenceType, initializers: Vec<Expression>) -> Self {
878        Element {
879            kind,
880            mode: ElementMode::Passive,
881            initializers,
882        }
883    }
884
885    /// Creates an active element segment.
886    pub fn active(
887        table: TableIndex,
888        offset: Expression,
889        kind: ReferenceType,
890        initializers: Vec<Expression>,
891    ) -> Self {
892        Element {
893            kind,
894            mode: ElementMode::Active(table, offset),
895            initializers,
896        }
897    }
898
899    /// Creates a declarative element segment.
900    pub fn declarative(kind: ReferenceType, initializers: Vec<Expression>) -> Self {
901        Element {
902            kind,
903            mode: ElementMode::Declarative,
904            initializers,
905        }
906    }
907
908    /// The reference type of the element segment.
909    pub fn kind(&self) -> ReferenceType {
910        self.kind
911    }
912
913    /// The initializer for the element segment.
914    pub fn initializers(&self) -> &[Expression] {
915        &self.initializers
916    }
917
918    /// The mode of the element segment.
919    pub fn mode(&self) -> &ElementMode {
920        &self.mode
921    }
922}
923
924/// Supported types for initializing an element component.
925pub trait ElementInitializer {
926    /// Maps this struct to a vector of expressions.
927    fn to_initializers(self) -> Vec<Expression>;
928}
929
930impl ElementInitializer for Vec<Expression> {
931    fn to_initializers(self) -> Vec<Expression> {
932        self
933    }
934}
935
936impl ElementInitializer for Vec<FunctionIndex> {
937    fn to_initializers(self) -> Vec<Expression> {
938        self.into_iter()
939            .map(|function| Expression::new(vec![ReferenceInstruction::Function(function).into()]))
940            .collect()
941    }
942}
943
944/// Element segments have a mode that identifies them as either passive, active, or declarative.
945#[derive(Clone, Debug, PartialEq)]
946pub enum ElementMode {
947    /// A passive element segmentβs elements can be copied to a table using the ππΊπ»π
πΎ.ππππ instruction.
948    Passive,
949    /// An active element segment copies its elements into a table during instantiation,
950    /// as specified by a table index and a constant expression defining an offset into that table.
951    /// The ππΏπΏππΎπ is given by a constant expression.
952    Active(TableIndex, Expression),
953    /// A declarative element segment is not available at runtime but merely serves to forward-declare
954    /// references that are formed in code with instructions like ππΎπΏ.πΏπππΌ.
955    Declarative,
956}
957
958/// The initial contents of a memory are zero bytes.
959/// Data segments can be used to initialize a range of memory from a static vector of bytes.
960/// Like element segments, data segments have a mode that identifies them as either passive or active.
961/// A passive data segmentβs contents can be copied into a memory using the ππΎππππ.ππππ instruction.
962/// An active data segment copies its contents into a memory during instantiation,
963/// as specified by a memory index and a constant expression defining an offset into that memory.
964/// Data segments are referenced through data indices.
965///
966/// See <https://webassembly.github.io/spec/core/syntax/modules.html#data-segments>
967///
968/// # Examples
969/// ## Passive
970/// ```rust
971/// use wasm_ast::{Data, DataMode};
972///
973/// let initializer = vec![42];
974/// let data = Data::passive(initializer.clone());
975///
976/// assert_eq!(data, Data::new(DataMode::Passive, initializer.clone()));
977/// assert_eq!(data, initializer.into());
978/// assert_eq!(data.mode(), &DataMode::Passive);
979/// assert_eq!(data.len(), 1);
980/// assert_eq!(data.is_empty(), false);
981/// ```
982///
983/// ## Active
984/// ```rust
985/// use wasm_ast::{Data, DataMode, MemoryIndex, Expression};
986///
987/// let initializer = vec![42];
988/// let offset: Expression = vec![1u32.into()].into();
989/// let data = Data::active(0, offset.clone(), initializer.clone());
990///
991/// assert_eq!(data, Data::new(DataMode::Active(0, offset.clone()), initializer.clone()));
992/// assert_eq!(data.mode(), &DataMode::Active(0, offset));
993/// assert_eq!(data.len(), 1);
994/// assert_eq!(data.is_empty(), false);
995/// ```
996#[derive(Clone, Debug, PartialEq)]
997pub struct Data {
998    mode: DataMode,
999    initializer: Vec<u8>,
1000}
1001
1002impl Data {
1003    /// Creates an instance of a data segment.
1004    pub fn new(mode: DataMode, initializer: Vec<u8>) -> Self {
1005        Data { mode, initializer }
1006    }
1007
1008    /// Creates an instance of a passive data segment.
1009    pub fn passive(initializer: Vec<u8>) -> Self {
1010        Data {
1011            mode: DataMode::Passive,
1012            initializer,
1013        }
1014    }
1015
1016    /// Creates an instance of an active data segment.
1017    pub fn active(memory: MemoryIndex, offset: Expression, initializer: Vec<u8>) -> Self {
1018        Data {
1019            mode: DataMode::Active(memory, offset),
1020            initializer,
1021        }
1022    }
1023
1024    /// The mode of the data segment.
1025    pub fn mode(&self) -> &DataMode {
1026        &self.mode
1027    }
1028
1029    /// The data to initialize the segment with.
1030    pub fn initializer(&self) -> &[u8] {
1031        &self.initializer
1032    }
1033
1034    /// The number of bytes in the data segment initializer.
1035    pub fn len(&self) -> usize {
1036        self.initializer.len()
1037    }
1038
1039    /// True if the data segment's initializer's length is zero, false otherwise.
1040    pub fn is_empty(&self) -> bool {
1041        self.initializer.is_empty()
1042    }
1043}
1044
1045impl From<Vec<u8>> for Data {
1046    fn from(initializer: Vec<u8>) -> Self {
1047        Data {
1048            mode: DataMode::Passive,
1049            initializer,
1050        }
1051    }
1052}
1053
1054/// Like element segments, data segments have a mode that identifies them as either passive or active.
1055#[derive(Clone, Debug, PartialEq)]
1056pub enum DataMode {
1057    /// A passive data segmentβs contents can be copied into a memory using the ππΎππππ.ππππ instruction.
1058    Passive,
1059    /// An active data segment copies its contents into a memory during instantiation,
1060    /// as specified by a memory index and a constant expression defining an offset into that memory.
1061    Active(MemoryIndex, Expression),
1062}
1063
1064/// The πππΊππ component of a module declares the function index of a start function that
1065/// is automatically invoked when the module is instantiated,
1066/// after tables and memories have been initialized.
1067/// start::={πΏπππΌ funcidx}
1068///
1069/// See <https://webassembly.github.io/spec/core/syntax/modules.html#start-function>
1070///
1071/// # Examples
1072/// ```rust
1073/// use wasm_ast::Start;
1074///
1075/// assert_eq!(Start::new(0).function(), 0);
1076/// ```
1077#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1078pub struct Start {
1079    function: FunctionIndex,
1080}
1081
1082impl Start {
1083    /// Creates a new instance of `Start` referencing the given function.
1084    pub fn new(function: FunctionIndex) -> Self {
1085        Start { function }
1086    }
1087
1088    /// The index of the function to run at module instantiation.
1089    pub fn function(&self) -> FunctionIndex {
1090        self.function
1091    }
1092}
1093
1094impl From<u32> for Start {
1095    fn from(function: u32) -> Self {
1096        Start { function }
1097    }
1098}
1099
1100/// The πΎππππππ component of a module defines a set of exports that become accessible to the
1101/// host environment once the module has been instantiated.
1102/// Each export is labeled by a unique name.
1103/// Exportable definitions are functions, tables, memories, and globals,
1104/// which are referenced through a respective descriptor.
1105///
1106/// See <https://webassembly.github.io/spec/core/syntax/modules.html#exports>
1107///
1108/// # Examples
1109/// ## Table
1110/// ```rust
1111/// use wasm_ast::{Export, ExportDescription, Name};
1112///
1113/// let name = "functions";
1114/// let description = ExportDescription::Table(0);
1115/// let export = Export::new(name.into(), description.clone());
1116///
1117/// assert_eq!(export, Export::table(name.into(), 0));
1118/// assert_eq!(export.name(), &Name::new(String::from(name)));
1119/// assert_eq!(export.description(), &description);
1120/// ```
1121///
1122/// ## Memory
1123/// ```rust
1124/// use wasm_ast::{Export, ExportDescription, Name};
1125///
1126/// let name = "io";
1127/// let description = ExportDescription::Memory(1);
1128/// let export = Export::new(name.into(), description.clone());
1129///
1130/// assert_eq!(export, Export::memory(name.into(), 1));
1131/// assert_eq!(export.name(), &Name::new(String::from(name)));
1132/// assert_eq!(export.description(), &description);
1133/// ```
1134///
1135/// ## Function
1136/// ```rust
1137/// use wasm_ast::{Export, ExportDescription, Name};
1138///
1139/// let name = "print";
1140/// let description = ExportDescription::Function(42);
1141/// let export = Export::new(name.into(), description.clone());
1142///
1143/// assert_eq!(export, Export::function(name.into(), 42));
1144/// assert_eq!(export.name(), &Name::new(String::from(name)));
1145/// assert_eq!(export.description(), &description);
1146/// ```
1147///
1148/// ## Global
1149/// ```rust
1150/// use wasm_ast::{Export, ExportDescription, Name};
1151///
1152/// let name = "functions";
1153/// let description = ExportDescription::Global(2);
1154/// let export = Export::new(name.into(), description.clone());
1155///
1156/// assert_eq!(export, Export::global(name.into(), 2));
1157/// assert_eq!(export.name(), &Name::new(String::from(name)));
1158/// assert_eq!(export.description(), &description);
1159/// ```
1160#[derive(Clone, Debug, Eq, PartialEq)]
1161pub struct Export {
1162    name: Name,
1163    description: ExportDescription,
1164}
1165
1166impl Export {
1167    /// Create a new instance of an `Export` with the given name and description.
1168    pub fn new(name: Name, description: ExportDescription) -> Self {
1169        Export { name, description }
1170    }
1171
1172    /// Create a new instance of an `Export` with the given name and description for a table.
1173    pub fn table(name: Name, table: TableIndex) -> Self {
1174        Export {
1175            name,
1176            description: ExportDescription::Table(table),
1177        }
1178    }
1179
1180    /// Create a new instance of an `Export` with the given name and description for a memory.
1181    pub fn memory(name: Name, memory: MemoryIndex) -> Self {
1182        Export {
1183            name,
1184            description: ExportDescription::Memory(memory),
1185        }
1186    }
1187
1188    /// Create a new instance of an `Export` with the given name and description for a function.
1189    pub fn function(name: Name, function: FunctionIndex) -> Self {
1190        Export {
1191            name,
1192            description: ExportDescription::Function(function),
1193        }
1194    }
1195
1196    /// Create a new instance of an `Export` with the given name and description for a global.
1197    pub fn global(name: Name, global: GlobalIndex) -> Self {
1198        Export {
1199            name,
1200            description: ExportDescription::Global(global),
1201        }
1202    }
1203
1204    /// The name of the export.
1205    pub fn name(&self) -> &Name {
1206        &self.name
1207    }
1208
1209    /// The description of the table.
1210    pub fn description(&self) -> &ExportDescription {
1211        &self.description
1212    }
1213}
1214
1215/// Exportable definitions are functions, tables, memories, and globals,
1216/// which are referenced through a respective descriptor.
1217#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1218pub enum ExportDescription {
1219    Function(FunctionIndex),
1220    Table(TableIndex),
1221    Memory(MemoryIndex),
1222    Global(GlobalIndex),
1223}
1224
1225/// Each import is labeled by a two-level name space,
1226/// consisting of a πππ½ππ
πΎ name and a ππΊππΎ for an entity within that module.
1227/// Importable definitions are functions, tables, memories, and globals.
1228/// Each import is specified by a descriptor with a respective type that a definition provided
1229/// during instantiation is required to match.
1230/// Every import defines an index in the respective index space.
1231/// In each index space, the indices of imports go before the first index of any
1232/// definition contained in the module itself.
1233///
1234/// See <https://webassembly.github.io/spec/core/syntax/modules.html#imports>
1235///
1236/// # Examples
1237/// ## Table
1238/// ```rust
1239/// use wasm_ast::{Import, ImportDescription, Name, TableType, Limit, ReferenceType};
1240///
1241/// let module = "system";
1242/// let name = "functions";
1243/// let kind = TableType::new( ReferenceType::Function,Limit::unbounded(1));
1244/// let description = ImportDescription::Table(kind.clone());
1245/// let import = Import::new(module.into(), name.into(), description.clone());
1246///
1247/// assert_eq!(import, Import::table(module.into(), name.into(), kind));
1248/// assert_eq!(import.module(), &Name::new(String::from(module)));
1249/// assert_eq!(import.name(), &Name::new(String::from(name)));
1250/// assert_eq!(import.description(), &description);
1251/// ```
1252///
1253/// ## Memory
1254/// ```rust
1255/// use wasm_ast::{Import, ImportDescription, Name, MemoryType, Limit};
1256///
1257/// let module = "system";
1258/// let name = "io";
1259/// let kind = Limit::bounded(1, 2).into();
1260/// let description = ImportDescription::Memory(kind);
1261/// let import = Import::new(module.into(), name.into(), description.clone());
1262///
1263/// assert_eq!(import, Import::memory(module.into(), name.into(), kind));
1264/// assert_eq!(import.module(), &Name::new(String::from(module)));
1265/// assert_eq!(import.name(), &Name::new(String::from(name)));
1266/// assert_eq!(import.description(), &description);
1267/// ```
1268///
1269/// ## Function
1270/// ```rust
1271/// use wasm_ast::{Import, ImportDescription, Name};
1272///
1273/// let module = "system";
1274/// let name = "print";
1275/// let description = ImportDescription::Function(42);
1276/// let import = Import::new(module.into(), name.into(), description.clone());
1277///
1278/// assert_eq!(import, Import::function(module.into(), name.into(), 42));
1279/// assert_eq!(import.module(), &Name::new(String::from(module)));
1280/// assert_eq!(import.name(), &Name::new(String::from(name)));
1281/// assert_eq!(import.description(), &description);
1282/// ```
1283///
1284/// ## Global
1285/// ```rust
1286/// use wasm_ast::{Import, ImportDescription, Name, GlobalType, ValueType};
1287///
1288/// let module = "system";
1289/// let name = "counter";
1290/// let kind = GlobalType::mutable(ValueType::I64);
1291/// let description = ImportDescription::Global(kind.clone());
1292/// let import = Import::new(module.into(), name.into(), description.clone());
1293///
1294/// assert_eq!(import, Import::global(module.into(), name.into(), kind));
1295/// assert_eq!(import.module(), &Name::new(String::from(module)));
1296/// assert_eq!(import.name(), &Name::new(String::from(name)));
1297/// assert_eq!(import.description(), &description);
1298/// ```
1299#[derive(Clone, Debug, Eq, PartialEq)]
1300pub struct Import {
1301    module: Name,
1302    name: Name,
1303    description: ImportDescription,
1304}
1305
1306impl Import {
1307    /// Creates a new import.
1308    pub fn new(module: Name, name: Name, description: ImportDescription) -> Self {
1309        Import {
1310            module,
1311            name,
1312            description,
1313        }
1314    }
1315
1316    /// Create a new instance of an `Import` with the given name and description for a table.
1317    pub fn table(module: Name, name: Name, table_kind: TableType) -> Self {
1318        Import {
1319            module,
1320            name,
1321            description: ImportDescription::Table(table_kind),
1322        }
1323    }
1324
1325    /// Create a new instance of an `Import` with the given name and description for a memory.
1326    pub fn memory(module: Name, name: Name, memory_kind: MemoryType) -> Self {
1327        Import {
1328            module,
1329            name,
1330            description: ImportDescription::Memory(memory_kind),
1331        }
1332    }
1333
1334    /// Create a new instance of an `Import` with the given name and description for a function.
1335    pub fn function(module: Name, name: Name, function_kind: TypeIndex) -> Self {
1336        Import {
1337            module,
1338            name,
1339            description: ImportDescription::Function(function_kind),
1340        }
1341    }
1342
1343    /// Create a new instance of an `Import` with the given name and description for a global.
1344    pub fn global(module: Name, name: Name, global_kind: GlobalType) -> Self {
1345        Import {
1346            module,
1347            name,
1348            description: ImportDescription::Global(global_kind),
1349        }
1350    }
1351
1352    /// The name of the module (i.e.m namespace).
1353    pub fn module(&self) -> &Name {
1354        &self.module
1355    }
1356
1357    /// The name of the import.
1358    pub fn name(&self) -> &Name {
1359        &self.name
1360    }
1361
1362    /// The description of the import.
1363    pub fn description(&self) -> &ImportDescription {
1364        &self.description
1365    }
1366}
1367
1368/// Each import is specified by a descriptor with a respective type that a definition provided
1369/// during instantiation is required to match.
1370#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1371pub enum ImportDescription {
1372    Function(TypeIndex),
1373    Table(TableType),
1374    Memory(MemoryType),
1375    Global(GlobalType),
1376}
1377
1378/// The binary encoding of modules is organized into sections.
1379/// Most sections correspond to one component of a module record,
1380/// except that function definitions are split into two sections,
1381/// separating their type declarations in the function section from their bodies in the code section.
1382///
1383/// See <https://webassembly.github.io/spec/core/binary/modules.html>
1384#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
1385pub enum ModuleSection {
1386    /// Custom sections have the id 0.
1387    /// They are intended to be used for debugging information or third-party extensions,
1388    /// and are ignored by the WebAssembly semantics.
1389    /// Their contents consist of a name further identifying the custom section,
1390    /// followed by an uninterpreted sequence of bytes for custom use.
1391    Custom = 0,
1392    /// The type section has the id 1.
1393    /// It decodes into a vector of function types that represent the ππππΎπ component of a module.
1394    Type,
1395    /// The import section has the id 2.
1396    /// It decodes into a vector of imports that represent the πππππππ component of a module.
1397    Import,
1398    /// The function section has the id 3.
1399    /// It decodes into a vector of type indices that represent the ππππΎ fields of the functions
1400    /// in the πΏπππΌπ component of a module. The π
ππΌπΊπ
π and π»ππ½π fields of the respective functions
1401    /// are encoded separately in the code section.
1402    Function,
1403    /// The table section has the id 4.
1404    /// It decodes into a vector of tables that represent the ππΊπ»π
πΎπ component of a module.
1405    Table,
1406    /// The memory section has the id 5.
1407    /// It decodes into a vector of memories that represent the ππΎππ component of a module.
1408    Memory,
1409    /// The global section has the id 6.
1410    /// It decodes into a vector of globals that represent the ππ
ππ»πΊπ
π component of a module.
1411    Global,
1412    /// The export section has the id 7.
1413    /// It decodes into a vector of exports that represent the πΎππππππ component of a module.
1414    Export,
1415    /// The start section has the id 8.
1416    /// It decodes into an optional start function that represents the πππΊππ component of a module.
1417    Start,
1418    /// The element section has the id 9.
1419    /// It decodes into a vector of element segments that represent the πΎπ
πΎππ component of a module.
1420    Element,
1421    /// The code section has the id 10.
1422    /// It decodes into a vector of code entries that are pairs of value type vectors and expressions.
1423    /// They represent the π
ππΌπΊπ
π and π»ππ½π field of the functions in the πΏπππΌπ component of a module.
1424    /// The ππππΎ fields of the respective functions are encoded separately in the function section.
1425    Code,
1426    /// The data section has the id 11.
1427    /// It decodes into a vector of data segments that represent the π½πΊππΊπ component of a module.
1428    Data,
1429    /// The data count section has the id 12.
1430    /// It decodes into an optional u32 that represents the number of data segments in the data section.
1431    /// If this count does not match the length of the data segment vector, the module is malformed.
1432    DataCount,
1433}
1434
1435#[cfg(test)]
1436mod tests {
1437    use super::*;
1438
1439    #[test]
1440    fn module_equality_when_empty() {
1441        assert_eq!(Module::builder().build(), Module::empty());
1442    }
1443
1444    #[test]
1445    fn module_equality_for_custom_sections() {
1446        let mut builder = Module::builder();
1447        builder.add_custom_section(
1448            ModuleSection::Data,
1449            Custom::new("version".into(), b"0.0.1".to_vec()),
1450        );
1451
1452        let module = builder.build();
1453
1454        assert_eq!(module, module.clone());
1455        assert_ne!(module, Module::empty());
1456    }
1457
1458    #[test]
1459    fn module_equality_not_same_custom_sections() {
1460        let mut builder = Module::builder();
1461        builder.add_custom_section(
1462            ModuleSection::Data,
1463            Custom::new("version".into(), b"0.0.1".to_vec()),
1464        );
1465
1466        let mut other_builder = Module::builder();
1467        other_builder.add_custom_section(
1468            ModuleSection::Export,
1469            Custom::new("version".into(), b"0.0.1".to_vec()),
1470        );
1471
1472        let module = builder.build();
1473        let other_module = other_builder.build();
1474
1475        assert_ne!(module, other_module);
1476    }
1477}