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