Skip to main content

tinywasm_types/
lib.rs

1#![doc(test(
2    no_crate_inject,
3    attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_assignments, unused_variables))
4))]
5#![warn(rust_2018_idioms, unreachable_pub)]
6#![no_std]
7#![deny(unsafe_code)]
8
9//! Types used by [`tinywasm`](https://docs.rs/tinywasm) and [`tinywasm_parser`](https://docs.rs/tinywasm_parser).
10
11extern crate alloc;
12use alloc::boxed::Box;
13use core::ops::{Deref, Range};
14
15#[cfg(all(not(feature = "portable-atomic"), not(target_has_atomic = "ptr")))]
16compile_error!(
17    "this target does not support atomic operations, enable the `portable-atomic` feature to use `portable-atomic`"
18);
19
20/// An atomically reference-counted pointer.
21#[cfg(not(feature = "portable-atomic"))]
22pub use alloc::sync::Arc as Shared;
23/// A non-owning pointer paired with [`Shared`].
24#[cfg(not(feature = "portable-atomic"))]
25pub use alloc::sync::Weak as WeakShared;
26/// An atomically reference-counted pointer.
27#[cfg(feature = "portable-atomic")]
28pub use portable_atomic_util::Arc as Shared;
29/// A non-owning pointer paired with [`Shared`].
30#[cfg(feature = "portable-atomic")]
31pub use portable_atomic_util::Weak as WeakShared;
32
33// Memory defaults
34const MEM_PAGE_SIZE: u64 = 65536;
35const fn max_page_count(arch: MemoryArch, page_size: u64) -> u64 {
36    match arch {
37        MemoryArch::I32 => (1u64 << 32) / page_size,
38        MemoryArch::I64 => u64::MAX / page_size,
39    }
40}
41
42mod instructions;
43mod operands;
44mod reference;
45mod types;
46mod value;
47pub use instructions::*;
48pub use operands::*;
49pub use reference::*;
50pub use types::*;
51pub use value::*;
52
53#[cfg(feature = "archive")]
54pub mod archive;
55
56#[cfg(not(feature = "archive"))]
57pub mod archive {
58    #[derive(Debug, PartialEq, Eq)]
59    pub enum TwasmError {}
60    impl core::fmt::Display for TwasmError {
61        fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
62            Err(core::fmt::Error)
63        }
64    }
65    impl core::error::Error for TwasmError {}
66}
67
68/// TinyWasm's parsed and lowered representation of a WebAssembly module.
69///
70/// Modules produced by the parser are validated by default, but validation can be
71/// disabled for trusted input. Do not trust modules or archives from third parties.
72///
73/// See <https://webassembly.github.io/spec/core/syntax/modules.html#syntax-module>
74#[derive(Clone, Default, PartialEq)]
75#[cfg_attr(feature = "debug", derive(Debug))]
76#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
77pub struct Module(Shared<ModuleInner>);
78
79impl From<ModuleInner> for Module {
80    fn from(inner: ModuleInner) -> Self {
81        Self(Shared::new(inner))
82    }
83}
84
85impl Deref for Module {
86    type Target = ModuleInner;
87
88    fn deref(&self) -> &ModuleInner {
89        &self.0
90    }
91}
92
93#[doc(hidden)]
94#[derive(Clone, Default, PartialEq)]
95#[cfg_attr(feature = "debug", derive(Debug))]
96#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
97pub struct ModuleInner {
98    /// Optional address of the start function
99    ///
100    /// Corresponds to the `start` section of the original WebAssembly module.
101    pub start_func: Option<FuncAddr>,
102
103    /// Optimized WebAssembly functions
104    ///
105    /// Contains data from to the `code`, `func`, and `type` sections of the original WebAssembly module.
106    pub funcs: Box<[Shared<WasmFunction>]>,
107
108    /// The dense type definitions, indexed by `TypeAddr`.
109    ///
110    /// Corresponds to the `type` section of the original WebAssembly module.
111    pub types: TypeSection,
112
113    /// Function index to type index mapping in module index space, including imports.
114    pub func_type_idxs: Box<[TypeAddr]>,
115
116    /// Exported items of the WebAssembly module.
117    ///
118    /// Corresponds to the `export` section of the original WebAssembly module.
119    pub exports: Shared<[Export]>,
120
121    /// Global components of the WebAssembly module.
122    ///
123    /// Corresponds to the `global` section of the original WebAssembly module.
124    pub globals: Box<[Global]>,
125
126    /// Table components of the WebAssembly module used to initialize tables.
127    ///
128    /// Corresponds to the `table` section of the original WebAssembly module.
129    pub tables: Box<[TableDefinition]>,
130
131    /// Memory components of the WebAssembly module used to initialize memories.
132    ///
133    /// Corresponds to the `memory` section of the original WebAssembly module.
134    pub memory_types: Box<[MemoryType]>,
135
136    /// Whether instantiation should omit unexported local memories that guest code cannot access.
137    pub skip_local_memory_allocation: bool,
138
139    /// Tag components of the WebAssembly module.
140    ///
141    /// Corresponds to the `tag` section of the original WebAssembly module.
142    pub tags: Box<[TagType]>,
143
144    /// Imports of the WebAssembly module.
145    ///
146    /// Corresponds to the `import` section of the original WebAssembly module.
147    pub imports: Box<[Import]>,
148
149    /// Data segments of the WebAssembly module.
150    ///
151    /// Corresponds to the `data` section of the original WebAssembly module.
152    pub data: Box<[Data]>,
153
154    /// Element segments of the WebAssembly module.
155    ///
156    /// Corresponds to the `elem` section of the original WebAssembly module.
157    pub elements: Box<[Element]>,
158}
159
160impl Module {
161    /// Returns an iterator over the module's import descriptors.
162    ///
163    /// The returned data mirrors the module's import section and preserves order.
164    pub fn imports(&self) -> impl Iterator<Item = ModuleImport<'_>> {
165        self.0.imports.iter().filter_map(|import| {
166            let ty = match &import.kind {
167                ImportKind::Function(type_idx) => Some(ImportType::Func(self.0.types.get(*type_idx)?.as_func()?)),
168                ImportKind::Table(table_ty) => Some(ImportType::Table(table_ty)),
169                ImportKind::Memory(memory_ty) => Some(ImportType::Memory(memory_ty)),
170                ImportKind::Global(global_ty) => Some(ImportType::Global(global_ty)),
171                ImportKind::Tag(tag_ty) => Some(ImportType::Tag(self.0.types.get(tag_ty.type_idx)?.as_func()?)),
172            }?;
173
174            Some(ModuleImport { module: import.module.as_ref(), name: import.name.as_ref(), ty })
175        })
176    }
177
178    /// Returns an iterator over the module's export descriptors.
179    ///
180    /// The returned data mirrors the module's export section and preserves order.
181    pub fn exports(&self) -> impl Iterator<Item = ModuleExport<'_>> {
182        fn imported_count(module: &ModuleInner, kind: ExternalKind) -> usize {
183            module
184                .imports
185                .iter()
186                .filter(|import| {
187                    matches!(
188                        (kind, &import.kind),
189                        (ExternalKind::Func, ImportKind::Function(_))
190                            | (ExternalKind::Table, ImportKind::Table(_))
191                            | (ExternalKind::Memory, ImportKind::Memory(_))
192                            | (ExternalKind::Global, ImportKind::Global(_))
193                            | (ExternalKind::Tag, ImportKind::Tag(_))
194                    )
195                })
196                .count()
197        }
198
199        fn imported_type(module: &ModuleInner, kind: ExternalKind, index: usize) -> Option<ExportType<'_>> {
200            let mut imports = module.imports.iter().filter(|import| {
201                matches!(
202                    (kind, &import.kind),
203                    (ExternalKind::Func, ImportKind::Function(_))
204                        | (ExternalKind::Table, ImportKind::Table(_))
205                        | (ExternalKind::Memory, ImportKind::Memory(_))
206                        | (ExternalKind::Global, ImportKind::Global(_))
207                        | (ExternalKind::Tag, ImportKind::Tag(_))
208                )
209            });
210            let import = imports.nth(index)?;
211
212            match &import.kind {
213                ImportKind::Function(type_idx) => Some(ExportType::Func(module.types.get(*type_idx)?.as_func()?)),
214                ImportKind::Table(table_ty) => Some(ExportType::Table(table_ty)),
215                ImportKind::Memory(memory_ty) => Some(ExportType::Memory(memory_ty)),
216                ImportKind::Global(global_ty) => Some(ExportType::Global(global_ty)),
217                ImportKind::Tag(tag_ty) => Some(ExportType::Tag(module.types.get(tag_ty.type_idx)?.as_func()?)),
218            }
219        }
220
221        self.0.exports.iter().filter_map(move |export| {
222            let idx = export.index as usize;
223            let ty = match export.kind {
224                ExternalKind::Func => {
225                    let imported_funcs = imported_count(&self.0, ExternalKind::Func);
226                    if idx < imported_funcs {
227                        imported_type(&self.0, ExternalKind::Func, idx)?
228                    } else {
229                        let type_idx = *self.0.func_type_idxs.get(idx)?;
230                        ExportType::Func(self.0.types.get(type_idx)?.as_func()?)
231                    }
232                }
233                ExternalKind::Table => {
234                    let imported_tables = imported_count(&self.0, ExternalKind::Table);
235                    if idx < imported_tables {
236                        imported_type(&self.0, ExternalKind::Table, idx)?
237                    } else {
238                        ExportType::Table(&self.0.tables.get(idx - imported_tables)?.ty)
239                    }
240                }
241                ExternalKind::Memory => {
242                    let imported_memories = imported_count(&self.0, ExternalKind::Memory);
243                    if idx < imported_memories {
244                        imported_type(&self.0, ExternalKind::Memory, idx)?
245                    } else {
246                        ExportType::Memory(self.0.memory_types.get(idx - imported_memories)?)
247                    }
248                }
249                ExternalKind::Global => {
250                    let imported_globals = imported_count(&self.0, ExternalKind::Global);
251                    if idx < imported_globals {
252                        imported_type(&self.0, ExternalKind::Global, idx)?
253                    } else {
254                        ExportType::Global(&self.0.globals.get(idx - imported_globals)?.ty)
255                    }
256                }
257                ExternalKind::Tag => {
258                    let imported_tags = imported_count(&self.0, ExternalKind::Tag);
259                    if idx < imported_tags {
260                        imported_type(&self.0, ExternalKind::Tag, idx)?
261                    } else {
262                        let tag_ty = self.0.tags.get(idx - imported_tags)?;
263                        ExportType::Tag(self.0.types.get(tag_ty.type_idx)?.as_func()?)
264                    }
265                }
266            };
267
268            Some(ModuleExport { name: export.name.as_ref(), ty })
269        })
270    }
271}
272
273/// A module export descriptor.
274pub struct ModuleExport<'a> {
275    /// Export name.
276    pub name: &'a str,
277    /// Export type.
278    pub ty: ExportType<'a>,
279}
280
281/// A module import descriptor.
282pub struct ModuleImport<'a> {
283    /// Importing module name.
284    pub module: &'a str,
285    /// Import name.
286    pub name: &'a str,
287    /// Import type.
288    pub ty: ImportType<'a>,
289}
290
291/// Imported entity type.
292pub enum ImportType<'a> {
293    /// Imported function type.
294    Func(&'a FuncType),
295    /// Imported table type.
296    Table(&'a TableType),
297    /// Imported memory type.
298    Memory(&'a MemoryType),
299    /// Imported global type.
300    Global(&'a GlobalType),
301    /// Imported tag type.
302    Tag(&'a FuncType),
303}
304
305/// Exported entity type.
306pub enum ExportType<'a> {
307    /// Exported function type.
308    Func(&'a FuncType),
309    /// Exported table type.
310    Table(&'a TableType),
311    /// Exported memory type.
312    Memory(&'a MemoryType),
313    /// Exported global type.
314    Global(&'a GlobalType),
315    /// Exported tag type.
316    Tag(&'a FuncType),
317}
318
319/// A WebAssembly External Kind.
320///
321/// See <https://webassembly.github.io/spec/core/syntax/types.html#external-types>
322#[derive(Clone, Copy, PartialEq, Eq)]
323#[cfg_attr(feature = "debug", derive(Debug))]
324#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
325pub enum ExternalKind {
326    /// A WebAssembly Function.
327    Func,
328    /// A WebAssembly Table.
329    Table,
330    /// A WebAssembly Memory.
331    Memory,
332    /// A WebAssembly Global.
333    Global,
334    /// A WebAssembly Tag.
335    Tag,
336}
337
338/// A WebAssembly Address.
339///
340/// These are indexes into the respective stores.
341///
342/// See <https://webassembly.github.io/spec/core/exec/runtime.html#addresses>
343pub type Addr = u32;
344
345// aliases for clarity
346pub type FuncAddr = Addr;
347pub type TableAddr = Addr;
348pub type MemAddr = Addr;
349pub type GlobalAddr = Addr;
350pub type TagAddr = Addr;
351pub type ElemAddr = Addr;
352pub type DataAddr = Addr;
353pub type ExternAddr = Addr;
354pub type ConstIdx = Addr;
355
356// additional internal addresses
357/// A function index in a WebAssembly module's function index space.
358///
359/// This remains module-local until instantiation resolves it to a [`FuncAddr`].
360#[derive(Clone, Copy, PartialEq, Eq, Hash)]
361#[cfg_attr(feature = "debug", derive(Debug))]
362#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
363#[cfg_attr(feature = "archive", serde(transparent))]
364pub struct ModuleFuncIdx(u32);
365
366impl ModuleFuncIdx {
367    /// Creates a module-local function index.
368    #[inline]
369    pub const fn new(index: u32) -> Self {
370        Self(index)
371    }
372
373    /// Returns the module-local function index.
374    #[inline]
375    pub const fn index(self) -> u32 {
376        self.0
377    }
378}
379
380/// An address in the current type space.
381///
382/// Parsed modules use module-local addresses; instantiated types use their store's canonical addresses.
383pub type TypeAddr = Addr;
384pub type LocalAddr = u16; // there can't be more than 50.000 locals in a function
385pub type ModuleInstanceId = Addr;
386
387/// A WebAssembly External Value.
388///
389/// See <https://webassembly.github.io/spec/core/exec/runtime.html#external-values>
390#[derive(Clone)]
391#[cfg_attr(feature = "debug", derive(Debug))]
392pub enum ExternVal {
393    Func(FuncAddr),
394    Table(TableAddr),
395    Memory(MemAddr),
396    Global(GlobalAddr),
397    Tag(TagAddr),
398}
399
400impl ExternVal {
401    #[inline]
402    pub const fn kind(&self) -> ExternalKind {
403        match self {
404            Self::Func(_) => ExternalKind::Func,
405            Self::Table(_) => ExternalKind::Table,
406            Self::Memory(_) => ExternalKind::Memory,
407            Self::Global(_) => ExternalKind::Global,
408            Self::Tag(_) => ExternalKind::Tag,
409        }
410    }
411
412    #[inline]
413    pub const fn new(kind: ExternalKind, addr: Addr) -> Self {
414        match kind {
415            ExternalKind::Func => Self::Func(addr),
416            ExternalKind::Table => Self::Table(addr),
417            ExternalKind::Memory => Self::Memory(addr),
418            ExternalKind::Global => Self::Global(addr),
419            ExternalKind::Tag => Self::Tag(addr),
420        }
421    }
422}
423
424/// The physical storage lane used by a [`WasmType`].
425#[derive(Clone, Copy, PartialEq, Eq)]
426#[cfg_attr(feature = "debug", derive(Debug))]
427pub enum ValueLane {
428    /// A 32-bit value or reference.
429    S32,
430    /// A 64-bit value.
431    S64,
432    /// A 128-bit SIMD value.
433    S128,
434}
435
436impl ValueLane {
437    /// Selects one of three values based on this lane.
438    pub fn select<T>(self, s32: T, s64: T, s128: T) -> T {
439        match self {
440            Self::S32 => s32,
441            Self::S64 => s64,
442            Self::S128 => s128,
443        }
444    }
445}
446
447impl From<&WasmType> for ValueLane {
448    fn from(ty: &WasmType) -> Self {
449        match ty {
450            WasmType::I32 | WasmType::F32 | WasmType::Ref(_) => Self::S32,
451            WasmType::I64 | WasmType::F64 => Self::S64,
452            WasmType::V128 => Self::S128,
453        }
454    }
455}
456
457#[derive(Default, Clone, Copy, PartialEq, Eq)]
458#[cfg_attr(feature = "debug", derive(Debug))]
459#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
460pub struct ValueCounts {
461    pub c32: u16,
462    pub c64: u16,
463    pub c128: u16,
464}
465
466impl ValueCounts {
467    #[inline]
468    pub fn is_empty(&self) -> bool {
469        self.c32 == 0 && self.c64 == 0 && self.c128 == 0
470    }
471}
472
473impl<'a> FromIterator<&'a WasmType> for ValueCounts {
474    #[inline]
475    fn from_iter<I: IntoIterator<Item = &'a WasmType>>(iter: I) -> Self {
476        let mut counts = Self::default();
477
478        for ty in iter {
479            match ValueLane::from(ty) {
480                ValueLane::S32 => counts.c32 += 1,
481                ValueLane::S64 => counts.c64 += 1,
482                ValueLane::S128 => counts.c128 += 1,
483            }
484        }
485        counts
486    }
487}
488
489#[derive(Clone, PartialEq, Default)]
490#[cfg_attr(feature = "debug", derive(Debug))]
491#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
492pub struct WasmFunction {
493    pub instructions: Box<[Instruction]>,
494    pub data: WasmFunctionData,
495    pub locals: ValueCounts,
496    pub params: ValueCounts,
497    pub results: ValueCounts,
498}
499
500#[derive(Clone, PartialEq, Eq, Default)]
501#[cfg_attr(feature = "debug", derive(Debug))]
502#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
503pub struct WasmFunctionData {
504    pub operands64: Box<[Operand64]>,
505    pub operands128: Box<[Operand128]>,
506    pub branch_table_targets: Box<[u32]>,
507    pub exception_handlers: Box<[ExceptionHandler]>,
508}
509
510/// A WebAssembly Module Export
511#[derive(Clone, PartialEq, Eq)]
512#[cfg_attr(feature = "debug", derive(Debug))]
513#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
514pub struct Export {
515    /// The name of the export.
516    pub name: Box<str>,
517    /// The kind of the export.
518    pub kind: ExternalKind,
519    /// The index of the exported item.
520    pub index: u32,
521}
522
523#[derive(Clone, PartialEq)]
524#[cfg_attr(feature = "debug", derive(Debug))]
525#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
526pub struct Global {
527    pub ty: GlobalType,
528    pub init: Box<[ConstInstruction]>,
529}
530
531/// A WebAssembly global type.
532///
533/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-globaltype>
534#[derive(Clone, Copy, PartialEq, Eq)]
535#[cfg_attr(feature = "debug", derive(Debug))]
536#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
537pub struct GlobalType {
538    pub mutable: bool,
539    pub ty: WasmType,
540}
541
542impl GlobalType {
543    /// Create a new global type.
544    pub const fn new(ty: WasmType, mutable: bool) -> Self {
545        Self { mutable, ty }
546    }
547
548    /// Set a different value type.
549    pub const fn with_ty(mut self, ty: WasmType) -> Self {
550        self.ty = ty;
551        self
552    }
553
554    /// Set global mutability.
555    pub const fn with_mutable(mut self, mutable: bool) -> Self {
556        self.mutable = mutable;
557        self
558    }
559}
560
561impl Default for GlobalType {
562    fn default() -> Self {
563        Self::new(WasmType::I32, false)
564    }
565}
566
567/// A WebAssembly table type.
568///
569/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-tabletype>
570#[derive(Copy, Clone, PartialEq, Eq)]
571#[cfg_attr(feature = "debug", derive(Debug))]
572#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
573pub struct TableType {
574    arch: MemoryArch,
575    pub element_type: RefType,
576    pub size_initial: u64,
577    pub size_max: Option<u64>,
578}
579
580#[derive(Clone, PartialEq)]
581#[cfg_attr(feature = "debug", derive(Debug))]
582#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
583pub struct TableDefinition {
584    pub ty: TableType,
585    pub init: Option<Box<[ConstInstruction]>>,
586}
587
588impl TableType {
589    pub const fn empty() -> Self {
590        Self::new(RefType::FUNCREF, 0, None)
591    }
592
593    /// Create a table with 32-bit indices.
594    pub const fn new(element_type: RefType, size_initial: u64, size_max: Option<u64>) -> Self {
595        Self { arch: MemoryArch::I32, element_type, size_initial, size_max }
596    }
597
598    /// Create a table with 64-bit indices.
599    pub const fn new64(element_type: RefType, size_initial: u64, size_max: Option<u64>) -> Self {
600        Self { arch: MemoryArch::I64, element_type, size_initial, size_max }
601    }
602
603    #[inline]
604    pub const fn arch(&self) -> MemoryArch {
605        self.arch
606    }
607}
608
609/// A WebAssembly memory type.
610///
611/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-memtype>
612#[derive(Copy, Clone, PartialEq, Eq)]
613#[cfg_attr(feature = "debug", derive(Debug))]
614#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
615pub struct MemoryType {
616    arch: MemoryArch,
617    page_count_initial: u64,
618    page_count_max: Option<u64>,
619    page_size: Option<u64>,
620}
621
622impl MemoryType {
623    /// Create a new memory type.
624    pub const fn new(
625        arch: MemoryArch,
626        page_count_initial: u64,
627        page_count_max: Option<u64>,
628        page_size: Option<u64>,
629    ) -> Self {
630        Self { arch, page_count_initial, page_count_max, page_size }
631    }
632
633    #[inline]
634    pub const fn arch(&self) -> MemoryArch {
635        self.arch
636    }
637
638    #[inline]
639    pub const fn page_count_initial(&self) -> u64 {
640        self.page_count_initial
641    }
642
643    #[inline]
644    pub const fn page_count_max(&self) -> u64 {
645        if let Some(page_count_max) = self.page_count_max {
646            page_count_max
647        } else {
648            max_page_count(self.arch, self.page_size())
649        }
650    }
651
652    /// Returns the declared maximum page count, or `None` if no maximum was declared.
653    #[inline]
654    pub const fn page_count_max_declared(&self) -> Option<u64> {
655        self.page_count_max
656    }
657
658    #[inline]
659    pub const fn page_size(&self) -> u64 {
660        if let Some(page_size) = self.page_size { page_size } else { MEM_PAGE_SIZE }
661    }
662
663    /// Set a different memory architecture.
664    pub const fn with_arch(mut self, arch: MemoryArch) -> Self {
665        self.arch = arch;
666        self
667    }
668
669    /// Set a different initial page count.
670    pub const fn with_page_count_initial(mut self, page_count_initial: u64) -> Self {
671        self.page_count_initial = page_count_initial;
672        self
673    }
674
675    /// Set a different maximum page count.
676    pub const fn with_page_count_max(mut self, page_count_max: Option<u64>) -> Self {
677        self.page_count_max = page_count_max;
678        self
679    }
680
681    /// Set a different page size.
682    pub const fn with_page_size(mut self, page_size: Option<u64>) -> Self {
683        self.page_size = page_size;
684        self
685    }
686}
687
688impl Default for MemoryType {
689    fn default() -> Self {
690        Self::new(MemoryArch::I32, 0, None, None)
691    }
692}
693
694#[derive(Copy, Clone, PartialEq, Eq, Hash)]
695#[cfg_attr(feature = "debug", derive(Debug))]
696#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
697pub enum MemoryArch {
698    I32,
699    I64,
700}
701
702/// A WebAssembly tag type.
703///
704/// See <https://webassembly.github.io/spec/core/syntax/types.html#syntax-tagtype>
705#[derive(Clone, Copy, PartialEq, Eq)]
706#[cfg_attr(feature = "debug", derive(Debug))]
707#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
708pub struct TagType {
709    /// The module-local function type index used by this tag.
710    pub type_idx: TypeAddr,
711}
712
713impl TagType {
714    /// Creates a tag type from a module-local function type index.
715    pub const fn new(type_idx: TypeAddr) -> Self {
716        Self { type_idx }
717    }
718}
719
720#[derive(Clone, PartialEq, Eq)]
721#[cfg_attr(feature = "debug", derive(Debug))]
722#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
723pub struct Import {
724    pub module: Box<str>,
725    pub name: Box<str>,
726    pub kind: ImportKind,
727}
728
729#[derive(Clone, PartialEq, Eq)]
730#[cfg_attr(feature = "debug", derive(Debug))]
731#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
732pub enum ImportKind {
733    Function(TypeAddr),
734    Table(TableType),
735    Memory(MemoryType),
736    Global(GlobalType),
737    Tag(TagType),
738}
739
740impl From<&ImportKind> for ExternalKind {
741    fn from(kind: &ImportKind) -> Self {
742        match kind {
743            ImportKind::Function(_) => Self::Func,
744            ImportKind::Table(_) => Self::Table,
745            ImportKind::Memory(_) => Self::Memory,
746            ImportKind::Global(_) => Self::Global,
747            ImportKind::Tag(_) => Self::Tag,
748        }
749    }
750}
751
752#[derive(Clone, PartialEq)]
753#[cfg_attr(feature = "debug", derive(Debug))]
754#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
755pub struct Data {
756    pub data: Shared<[u8]>,
757    pub range: Range<u64>,
758    pub kind: DataKind,
759}
760
761#[derive(Clone, PartialEq)]
762#[cfg_attr(feature = "debug", derive(Debug))]
763#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
764pub enum DataKind {
765    Active { mem: MemAddr, offset: Box<[ConstInstruction]> },
766    Passive,
767}
768
769#[derive(Clone, PartialEq)]
770#[cfg_attr(feature = "debug", derive(Debug))]
771#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
772pub struct Element {
773    pub kind: ElementKind,
774    pub items: Box<[ElementItem]>,
775    pub range: Range<u64>,
776    pub ty: RefType,
777}
778
779#[derive(Clone, PartialEq)]
780#[cfg_attr(feature = "debug", derive(Debug))]
781#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
782pub enum ElementKind {
783    Passive,
784    Active { table: TableAddr, offset: Box<[ConstInstruction]> },
785    Declared,
786}
787
788#[derive(Clone, PartialEq)]
789#[cfg_attr(feature = "debug", derive(Debug))]
790#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
791pub enum ElementItem {
792    Func(FuncAddr),
793    Expr(Box<[ConstInstruction]>),
794}