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, sync::Arc};
13use core::hint::cold_path;
14use core::ops::{Deref, Range};
15
16// Memory defaults
17const MEM_PAGE_SIZE: u64 = 65536;
18const MAX_MEMORY_SIZE: u64 = 4294967296;
19
20const fn max_page_count(page_size: u64) -> u64 {
21    MAX_MEMORY_SIZE / page_size
22}
23
24// log for logging (optional).
25#[cfg(feature = "log")]
26#[allow(clippy::single_component_path_imports, unused_imports)]
27use log;
28
29// noop fallback if logging is disabled.
30#[cfg(not(feature = "log"))]
31#[allow(unused_imports, unused_macros)]
32pub(crate) mod log {
33    macro_rules! debug    ( ($($tt:tt)*) => {{}} );
34    macro_rules! info    ( ($($tt:tt)*) => {{}} );
35    macro_rules! error    ( ($($tt:tt)*) => {{}} );
36    pub(crate) use debug;
37    pub(crate) use error;
38    pub(crate) use info;
39}
40
41mod instructions;
42mod value;
43pub use instructions::*;
44pub use value::*;
45
46#[cfg(feature = "archive")]
47pub mod archive;
48
49#[cfg(not(feature = "archive"))]
50pub mod archive {
51    #[derive(Debug)]
52    pub enum TwasmError {}
53    impl core::fmt::Display for TwasmError {
54        fn fmt(&self, _: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55            Err(core::fmt::Error)
56        }
57    }
58    impl core::error::Error for TwasmError {}
59}
60
61/// A `TinyWasm` WebAssembly Module
62///
63/// This is the internal representation of a WebAssembly module in `TinyWasm`.
64/// [`Module`] are validated before being created, so they are guaranteed to be valid (as long as they were created by `TinyWasm`).
65/// This means you should not trust a [`Module`] created by a third party to be valid.
66#[derive(Clone, Default, PartialEq)]
67#[cfg_attr(feature = "debug", derive(Debug))]
68#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
69pub struct Module(Arc<ModuleInner>);
70
71impl From<ModuleInner> for Module {
72    fn from(inner: ModuleInner) -> Self {
73        Self(Arc::new(inner))
74    }
75}
76
77impl Deref for Module {
78    type Target = ModuleInner;
79
80    fn deref(&self) -> &ModuleInner {
81        &self.0
82    }
83}
84
85#[doc(hidden)]
86#[derive(Clone, Default, PartialEq)]
87#[cfg_attr(feature = "debug", derive(Debug))]
88#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
89pub struct ModuleInner {
90    /// Optional address of the start function
91    ///
92    /// Corresponds to the `start` section of the original WebAssembly module.
93    pub start_func: Option<FuncAddr>,
94
95    /// Optimized and validated WebAssembly functions
96    ///
97    /// Contains data from to the `code`, `func`, and `type` sections of the original WebAssembly module.
98    pub funcs: Box<[Arc<WasmFunction>]>,
99
100    /// A vector of type definitions, indexed by `TypeAddr`
101    ///
102    /// Corresponds to the `type` section of the original WebAssembly module.
103    pub func_types: Arc<[Arc<FuncType>]>,
104
105    /// Function index to type index mapping in module index space, including imports.
106    pub func_type_idxs: Arc<[u32]>,
107
108    /// Exported items of the WebAssembly module.
109    ///
110    /// Corresponds to the `export` section of the original WebAssembly module.
111    pub exports: Arc<[Export]>,
112
113    /// Global components of the WebAssembly module.
114    ///
115    /// Corresponds to the `global` section of the original WebAssembly module.
116    pub globals: Box<[Global]>,
117
118    /// Table components of the WebAssembly module used to initialize tables.
119    ///
120    /// Corresponds to the `table` section of the original WebAssembly module.
121    pub table_types: Box<[TableType]>,
122
123    /// Memory components of the WebAssembly module used to initialize memories.
124    ///
125    /// Corresponds to the `memory` section of the original WebAssembly module.
126    pub memory_types: Box<[MemoryType]>,
127
128    /// Imports of the WebAssembly module.
129    ///
130    /// Corresponds to the `import` section of the original WebAssembly module.
131    pub imports: Box<[Import]>,
132
133    /// Data segments of the WebAssembly module.
134    ///
135    /// Corresponds to the `data` section of the original WebAssembly module.
136    pub data: Box<[Data]>,
137
138    /// Element segments of the WebAssembly module.
139    ///
140    /// Corresponds to the `elem` section of the original WebAssembly module.
141    pub elements: Box<[Element]>,
142
143    /// How instantiation should prepare the module's local memories.
144    pub local_memory_allocation: LocalMemoryAllocation,
145}
146
147impl Module {
148    /// Returns an iterator over the module's import descriptors.
149    ///
150    /// The returned data mirrors the module's import section and preserves order.
151    pub fn imports(&self) -> impl Iterator<Item = ModuleImport<'_>> {
152        self.0.imports.iter().filter_map(|import| {
153            let ty = match &import.kind {
154                ImportKind::Function(type_idx) => Some(ImportType::Func(self.0.func_types.get(*type_idx as usize)?)),
155                ImportKind::Table(table_ty) => Some(ImportType::Table(table_ty)),
156                ImportKind::Memory(memory_ty) => Some(ImportType::Memory(memory_ty)),
157                ImportKind::Global(global_ty) => Some(ImportType::Global(global_ty)),
158            }?;
159
160            Some(ModuleImport { module: import.module.as_ref(), name: import.name.as_ref(), ty })
161        })
162    }
163
164    /// Returns an iterator over the module's export descriptors.
165    ///
166    /// The returned data mirrors the module's export section and preserves order.
167    pub fn exports(&self) -> impl Iterator<Item = ModuleExport<'_>> {
168        fn imported_count(module: &ModuleInner, kind: ExternalKind) -> usize {
169            module
170                .imports
171                .iter()
172                .filter(|import| {
173                    matches!(
174                        (kind, &import.kind),
175                        (ExternalKind::Func, ImportKind::Function(_))
176                            | (ExternalKind::Table, ImportKind::Table(_))
177                            | (ExternalKind::Memory, ImportKind::Memory(_))
178                            | (ExternalKind::Global, ImportKind::Global(_))
179                    )
180                })
181                .count()
182        }
183
184        fn imported_func_type(module: &ModuleInner, function_index: usize) -> Option<&FuncType> {
185            let mut seen = 0usize;
186            for import in module.imports.iter() {
187                if let ImportKind::Function(type_idx) = import.kind {
188                    if seen == function_index {
189                        return module.func_types.get(type_idx as usize).map(|ty| &**ty);
190                    }
191                    seen += 1;
192                }
193            }
194            None
195        }
196
197        fn imported_table_type(module: &ModuleInner, table_index: usize) -> Option<&TableType> {
198            let mut seen = 0usize;
199            for import in module.imports.iter() {
200                if let ImportKind::Table(table_ty) = &import.kind {
201                    if seen == table_index {
202                        return Some(table_ty);
203                    }
204                    seen += 1;
205                }
206            }
207            None
208        }
209
210        fn imported_memory_type(module: &ModuleInner, memory_index: usize) -> Option<&MemoryType> {
211            let mut seen = 0usize;
212            for import in module.imports.iter() {
213                if let ImportKind::Memory(memory_ty) = &import.kind {
214                    if seen == memory_index {
215                        return Some(memory_ty);
216                    }
217                    seen += 1;
218                }
219            }
220            None
221        }
222
223        fn imported_global_type(module: &Module, global_index: usize) -> Option<&GlobalType> {
224            let mut seen = 0usize;
225            for import in module.imports.iter() {
226                if let ImportKind::Global(global_ty) = &import.kind {
227                    if seen == global_index {
228                        return Some(global_ty);
229                    }
230                    seen += 1;
231                }
232            }
233            None
234        }
235
236        self.0.exports.iter().filter_map(move |export| {
237            let idx = export.index as usize;
238            let ty = match export.kind {
239                ExternalKind::Func => {
240                    let imported_funcs = imported_count(&self.0, ExternalKind::Func);
241                    if idx < imported_funcs {
242                        ExportType::Func(imported_func_type(&self.0, idx)?)
243                    } else {
244                        let local_idx = idx - imported_funcs;
245                        ExportType::Func(&self.0.funcs.get(local_idx)?.ty)
246                    }
247                }
248                ExternalKind::Table => {
249                    let imported_tables = imported_count(&self.0, ExternalKind::Table);
250                    if idx < imported_tables {
251                        ExportType::Table(imported_table_type(&self.0, idx)?)
252                    } else {
253                        let local_idx = idx - imported_tables;
254                        ExportType::Table(self.0.table_types.get(local_idx)?)
255                    }
256                }
257                ExternalKind::Memory => {
258                    let imported_memories = imported_count(&self.0, ExternalKind::Memory);
259                    if idx < imported_memories {
260                        ExportType::Memory(imported_memory_type(&self.0, idx)?)
261                    } else {
262                        let local_idx = idx - imported_memories;
263                        ExportType::Memory(self.0.memory_types.get(local_idx)?)
264                    }
265                }
266                ExternalKind::Global => {
267                    let imported_globals = imported_count(&self.0, ExternalKind::Global);
268                    if idx < imported_globals {
269                        ExportType::Global(imported_global_type(self, idx)?)
270                    } else {
271                        let local_idx = idx - imported_globals;
272                        ExportType::Global(&self.0.globals.get(local_idx)?.ty)
273                    }
274                }
275            };
276
277            Some(ModuleExport { name: export.name.as_ref(), ty })
278        })
279    }
280}
281
282/// A module export descriptor.
283pub struct ModuleExport<'a> {
284    /// Export name.
285    pub name: &'a str,
286    /// Export type.
287    pub ty: ExportType<'a>,
288}
289
290/// A module import descriptor.
291pub struct ModuleImport<'a> {
292    /// Importing module name.
293    pub module: &'a str,
294    /// Import name.
295    pub name: &'a str,
296    /// Import type.
297    pub ty: ImportType<'a>,
298}
299
300/// Imported entity type.
301pub enum ImportType<'a> {
302    /// Imported function type.
303    Func(&'a FuncType),
304    /// Imported table type.
305    Table(&'a TableType),
306    /// Imported memory type.
307    Memory(&'a MemoryType),
308    /// Imported global type.
309    Global(&'a GlobalType),
310}
311
312/// Exported entity type.
313pub enum ExportType<'a> {
314    /// Exported function type.
315    Func(&'a FuncType),
316    /// Exported table type.
317    Table(&'a TableType),
318    /// Exported memory type.
319    Memory(&'a MemoryType),
320    /// Exported global type.
321    Global(&'a GlobalType),
322}
323
324/// How instantiation should prepare local memories declared by the module.
325#[derive(Clone, Copy, PartialEq, Eq, Default)]
326#[cfg_attr(feature = "debug", derive(Debug))]
327#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
328pub enum LocalMemoryAllocation {
329    /// The module's local memories are unobservable and can be skipped entirely.
330    #[default]
331    Skip,
332    /// The module's local memories may be observed through exports, but can be delayed until first use.
333    Lazy,
334    /// The module's local memories must be allocated during instantiation.
335    Eager,
336}
337
338/// A WebAssembly External Kind.
339///
340/// See <https://webassembly.github.io/spec/core/syntax/types.html#external-types>
341#[derive(Clone, Copy, PartialEq, Eq)]
342#[cfg_attr(feature = "debug", derive(Debug))]
343#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
344pub enum ExternalKind {
345    /// A WebAssembly Function.
346    Func,
347    /// A WebAssembly Table.
348    Table,
349    /// A WebAssembly Memory.
350    Memory,
351    /// A WebAssembly Global.
352    Global,
353}
354
355/// A WebAssembly Address.
356///
357/// These are indexes into the respective stores.
358///
359/// See <https://webassembly.github.io/spec/core/exec/runtime.html#addresses>
360pub type Addr = u32;
361
362// aliases for clarity
363pub type FuncAddr = Addr;
364pub type TableAddr = Addr;
365pub type MemAddr = Addr;
366pub type GlobalAddr = Addr;
367pub type ElemAddr = Addr;
368pub type DataAddr = Addr;
369pub type ExternAddr = Addr;
370pub type ConstIdx = Addr;
371
372// additional internal addresses
373pub type TypeAddr = Addr;
374pub type LocalAddr = u16; // there can't be more than 50.000 locals in a function
375pub type ModuleInstanceAddr = Addr;
376
377/// A WebAssembly External Value.
378///
379/// See <https://webassembly.github.io/spec/core/exec/runtime.html#external-values>
380#[derive(Clone)]
381#[cfg_attr(feature = "debug", derive(Debug))]
382pub enum ExternVal {
383    Func(FuncAddr),
384    Table(TableAddr),
385    Memory(MemAddr),
386    Global(GlobalAddr),
387}
388
389impl ExternVal {
390    #[inline]
391    pub const fn kind(&self) -> ExternalKind {
392        match self {
393            Self::Func(_) => ExternalKind::Func,
394            Self::Table(_) => ExternalKind::Table,
395            Self::Memory(_) => ExternalKind::Memory,
396            Self::Global(_) => ExternalKind::Global,
397        }
398    }
399
400    #[inline]
401    pub const fn new(kind: ExternalKind, addr: Addr) -> Self {
402        match kind {
403            ExternalKind::Func => Self::Func(addr),
404            ExternalKind::Table => Self::Table(addr),
405            ExternalKind::Memory => Self::Memory(addr),
406            ExternalKind::Global => Self::Global(addr),
407        }
408    }
409}
410
411/// The type of a WebAssembly Function.
412///
413/// See <https://webassembly.github.io/spec/core/syntax/types.html#function-types>
414#[derive(Clone, PartialEq, Eq, Default)]
415#[cfg_attr(feature = "debug", derive(Debug))]
416#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
417pub struct FuncType {
418    data: Box<[WasmType]>,
419    param_count: u16,
420}
421
422impl FuncType {
423    /// Create a new function type.
424    pub fn new(params: &[WasmType], results: &[WasmType]) -> Self {
425        let param_count = params.len() as u16;
426        let data: Box<[WasmType]> = params.iter().cloned().chain(results.iter().cloned()).collect();
427        Self { data, param_count }
428    }
429
430    /// Get the parameter types of this function type.
431    pub fn params(&self) -> &[WasmType] {
432        &self.data[..self.param_count as usize]
433    }
434
435    /// Get the result types of this function type.
436    pub fn results(&self) -> &[WasmType] {
437        &self.data[self.param_count as usize..]
438    }
439}
440
441#[derive(Default, Clone, Copy, PartialEq, Eq)]
442#[cfg_attr(feature = "debug", derive(Debug))]
443#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
444pub struct ValueCounts {
445    pub c32: u16,
446    pub c64: u16,
447    pub c128: u16,
448}
449
450impl ValueCounts {
451    #[inline]
452    pub fn is_empty(&self) -> bool {
453        self.c32 == 0 && self.c64 == 0 && self.c128 == 0
454    }
455}
456
457impl<'a> FromIterator<&'a WasmType> for ValueCounts {
458    #[inline]
459    fn from_iter<I: IntoIterator<Item = &'a WasmType>>(iter: I) -> Self {
460        let mut counts = Self::default();
461
462        for ty in iter {
463            match ty {
464                WasmType::I32 | WasmType::F32 | WasmType::RefExtern | WasmType::RefFunc => counts.c32 += 1,
465                WasmType::I64 | WasmType::F64 => counts.c64 += 1,
466                WasmType::V128 => counts.c128 += 1,
467            }
468        }
469        counts
470    }
471}
472
473#[derive(Clone, PartialEq, Default)]
474#[cfg_attr(feature = "debug", derive(Debug))]
475#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
476pub struct WasmFunction {
477    pub instructions: Box<[Instruction]>,
478    pub data: WasmFunctionData,
479    pub locals: ValueCounts,
480    pub params: ValueCounts,
481    pub results: ValueCounts,
482    pub ty: Arc<FuncType>,
483}
484
485#[derive(Clone, PartialEq, Eq, Default)]
486#[cfg_attr(feature = "debug", derive(Debug))]
487#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
488pub struct WasmFunctionData {
489    pub v128_constants: Box<[[u8; 16]]>,
490    pub branch_table_targets: Box<[u32]>,
491}
492
493impl WasmFunctionData {
494    /// Panics if `idx` is out of bounds.
495    #[inline(always)]
496    pub fn v128_const(&self, idx: ConstIdx) -> [u8; 16] {
497        let Some(val) = self.v128_constants.get(idx as usize) else {
498            cold_path();
499            unreachable!("invalid v128 constant index");
500        };
501        *val
502    }
503}
504
505/// A WebAssembly Module Export
506#[derive(Clone, PartialEq, Eq)]
507#[cfg_attr(feature = "debug", derive(Debug))]
508#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
509pub struct Export {
510    /// The name of the export.
511    pub name: Box<str>,
512    /// The kind of the export.
513    pub kind: ExternalKind,
514    /// The index of the exported item.
515    pub index: u32,
516}
517
518#[derive(Clone, PartialEq)]
519#[cfg_attr(feature = "debug", derive(Debug))]
520#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
521pub struct Global {
522    pub ty: GlobalType,
523    pub init: Box<[ConstInstruction]>,
524}
525
526#[derive(Clone, Copy, PartialEq, Eq)]
527#[cfg_attr(feature = "debug", derive(Debug))]
528#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
529pub struct GlobalType {
530    pub mutable: bool,
531    pub ty: WasmType,
532}
533
534impl GlobalType {
535    /// Create a new global type.
536    pub const fn new(ty: WasmType, mutable: bool) -> Self {
537        Self { mutable, ty }
538    }
539
540    /// Set a different value type.
541    pub const fn with_ty(mut self, ty: WasmType) -> Self {
542        self.ty = ty;
543        self
544    }
545
546    /// Set global mutability.
547    pub const fn with_mutable(mut self, mutable: bool) -> Self {
548        self.mutable = mutable;
549        self
550    }
551}
552
553impl Default for GlobalType {
554    fn default() -> Self {
555        Self::new(WasmType::I32, false)
556    }
557}
558
559#[derive(Clone, PartialEq, Eq)]
560#[cfg_attr(feature = "debug", derive(Debug))]
561#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
562pub struct TableType {
563    pub element_type: WasmType,
564    pub size_initial: u32,
565    pub size_max: Option<u32>,
566}
567
568impl TableType {
569    pub fn empty() -> Self {
570        Self { element_type: WasmType::RefFunc, size_initial: 0, size_max: None }
571    }
572
573    pub fn new(element_type: WasmType, size_initial: u32, size_max: Option<u32>) -> Self {
574        Self { element_type, size_initial, size_max }
575    }
576}
577
578/// Represents a memory's type.
579#[derive(Copy, Clone, PartialEq, Eq)]
580#[cfg_attr(feature = "debug", derive(Debug))]
581#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
582pub struct MemoryType {
583    arch: MemoryArch,
584    page_count_initial: u64,
585    page_count_max: Option<u64>,
586    page_size: Option<u64>,
587}
588
589impl MemoryType {
590    /// Create a new memory type.
591    pub const fn new(
592        arch: MemoryArch,
593        page_count_initial: u64,
594        page_count_max: Option<u64>,
595        page_size: Option<u64>,
596    ) -> Self {
597        Self { arch, page_count_initial, page_count_max, page_size }
598    }
599
600    #[inline]
601    pub const fn arch(&self) -> MemoryArch {
602        self.arch
603    }
604
605    #[inline]
606    pub const fn page_count_initial(&self) -> u64 {
607        self.page_count_initial
608    }
609
610    #[inline]
611    pub const fn page_count_max(&self) -> u64 {
612        if let Some(page_count_max) = self.page_count_max { page_count_max } else { max_page_count(self.page_size()) }
613    }
614
615    #[inline]
616    pub const fn page_size(&self) -> u64 {
617        if let Some(page_size) = self.page_size { page_size } else { MEM_PAGE_SIZE }
618    }
619
620    #[inline]
621    pub const fn initial_size(&self) -> u64 {
622        self.page_count_initial * self.page_size()
623    }
624
625    #[inline]
626    pub const fn max_size(&self) -> u64 {
627        self.page_count_max() * self.page_size()
628    }
629
630    /// Set a different memory architecture.
631    pub const fn with_arch(mut self, arch: MemoryArch) -> Self {
632        self.arch = arch;
633        self
634    }
635
636    /// Set a different initial page count.
637    pub const fn with_page_count_initial(mut self, page_count_initial: u64) -> Self {
638        self.page_count_initial = page_count_initial;
639        self
640    }
641
642    /// Set a different maximum page count.
643    pub const fn with_page_count_max(mut self, page_count_max: Option<u64>) -> Self {
644        self.page_count_max = page_count_max;
645        self
646    }
647
648    /// Set a different page size.
649    pub const fn with_page_size(mut self, page_size: Option<u64>) -> Self {
650        self.page_size = page_size;
651        self
652    }
653}
654
655impl Default for MemoryType {
656    fn default() -> Self {
657        Self::new(MemoryArch::I32, 0, None, None)
658    }
659}
660
661#[derive(Copy, Clone, PartialEq, Eq, Hash)]
662#[cfg_attr(feature = "debug", derive(Debug))]
663#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
664pub enum MemoryArch {
665    I32,
666    I64,
667}
668
669#[derive(Clone, PartialEq, Eq)]
670#[cfg_attr(feature = "debug", derive(Debug))]
671#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
672pub struct Import {
673    pub module: Box<str>,
674    pub name: Box<str>,
675    pub kind: ImportKind,
676}
677
678#[derive(Clone, PartialEq, Eq)]
679#[cfg_attr(feature = "debug", derive(Debug))]
680#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
681pub enum ImportKind {
682    Function(TypeAddr),
683    Table(TableType),
684    Memory(MemoryType),
685    Global(GlobalType),
686}
687
688impl From<&ImportKind> for ExternalKind {
689    fn from(kind: &ImportKind) -> Self {
690        match kind {
691            ImportKind::Function(_) => Self::Func,
692            ImportKind::Table(_) => Self::Table,
693            ImportKind::Memory(_) => Self::Memory,
694            ImportKind::Global(_) => Self::Global,
695        }
696    }
697}
698
699#[derive(Clone, PartialEq)]
700#[cfg_attr(feature = "debug", derive(Debug))]
701#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
702pub struct Data {
703    pub data: Box<[u8]>,
704    pub range: Range<usize>,
705    pub kind: DataKind,
706}
707
708#[derive(Clone, PartialEq)]
709#[cfg_attr(feature = "debug", derive(Debug))]
710#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
711pub enum DataKind {
712    Active { mem: MemAddr, offset: Box<[ConstInstruction]> },
713    Passive,
714}
715
716#[derive(Clone, PartialEq)]
717#[cfg_attr(feature = "debug", derive(Debug))]
718#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
719pub struct Element {
720    pub kind: ElementKind,
721    pub items: Box<[ElementItem]>,
722    pub range: Range<usize>,
723    pub ty: WasmType,
724}
725
726#[derive(Clone, PartialEq)]
727#[cfg_attr(feature = "debug", derive(Debug))]
728#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
729pub enum ElementKind {
730    Passive,
731    Active { table: TableAddr, offset: Box<[ConstInstruction]> },
732    Declared,
733}
734
735#[derive(Clone, PartialEq)]
736#[cfg_attr(feature = "debug", derive(Debug))]
737#[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))]
738pub enum ElementItem {
739    Func(FuncAddr),
740    Expr(Box<[ConstInstruction]>),
741}