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}