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(missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
6#![no_std]
7#![forbid(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::{fmt::Debug, ops::Range};
14
15// log for logging (optional).
16#[cfg(feature = "logging")]
17#[allow(clippy::single_component_path_imports, unused_imports)]
18use log;
19
20// noop fallback if logging is disabled.
21#[cfg(not(feature = "logging"))]
22#[allow(unused_imports, unused_macros)]
23pub(crate) mod log {
24    macro_rules! debug    ( ($($tt:tt)*) => {{}} );
25    macro_rules! info    ( ($($tt:tt)*) => {{}} );
26    macro_rules! error    ( ($($tt:tt)*) => {{}} );
27    pub(crate) use debug;
28    pub(crate) use error;
29    pub(crate) use info;
30}
31
32mod instructions;
33mod value;
34pub use instructions::*;
35pub use value::*;
36
37#[cfg(feature = "archive")]
38pub mod archive;
39
40/// A `TinyWasm` WebAssembly Module
41///
42/// This is the internal representation of a WebAssembly module in `TinyWasm`.
43/// `TinyWasmModules` are validated before being created, so they are guaranteed to be valid (as long as they were created by `TinyWasm`).
44/// This means you should not trust a `TinyWasmModule` created by a third party to be valid.
45#[derive(Debug, Clone, Default, PartialEq)]
46#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
47pub struct TinyWasmModule {
48    /// Optional address of the start function
49    ///
50    /// Corresponds to the `start` section of the original WebAssembly module.
51    pub start_func: Option<FuncAddr>,
52
53    /// Optimized and validated WebAssembly functions
54    ///
55    /// Contains data from to the `code`, `func`, and `type` sections of the original WebAssembly module.
56    pub funcs: Box<[WasmFunction]>,
57
58    /// A vector of type definitions, indexed by `TypeAddr`
59    ///
60    /// Corresponds to the `type` section of the original WebAssembly module.
61    pub func_types: Box<[FuncType]>,
62
63    /// Exported items of the WebAssembly module.
64    ///
65    /// Corresponds to the `export` section of the original WebAssembly module.
66    pub exports: Box<[Export]>,
67
68    /// Global components of the WebAssembly module.
69    ///
70    /// Corresponds to the `global` section of the original WebAssembly module.
71    pub globals: Box<[Global]>,
72
73    /// Table components of the WebAssembly module used to initialize tables.
74    ///
75    /// Corresponds to the `table` section of the original WebAssembly module.
76    pub table_types: Box<[TableType]>,
77
78    /// Memory components of the WebAssembly module used to initialize memories.
79    ///
80    /// Corresponds to the `memory` section of the original WebAssembly module.
81    pub memory_types: Box<[MemoryType]>,
82
83    /// Imports of the WebAssembly module.
84    ///
85    /// Corresponds to the `import` section of the original WebAssembly module.
86    pub imports: Box<[Import]>,
87
88    /// Data segments of the WebAssembly module.
89    ///
90    /// Corresponds to the `data` section of the original WebAssembly module.
91    pub data: Box<[Data]>,
92
93    /// Element segments of the WebAssembly module.
94    ///
95    /// Corresponds to the `elem` section of the original WebAssembly module.
96    pub elements: Box<[Element]>,
97}
98
99/// A WebAssembly External Kind.
100///
101/// See <https://webassembly.github.io/spec/core/syntax/types.html#external-types>
102#[derive(Debug, Clone, Copy, PartialEq)]
103#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
104pub enum ExternalKind {
105    /// A WebAssembly Function.
106    Func,
107    /// A WebAssembly Table.
108    Table,
109    /// A WebAssembly Memory.
110    Memory,
111    /// A WebAssembly Global.
112    Global,
113}
114
115/// A WebAssembly Address.
116///
117/// These are indexes into the respective stores.
118///
119/// See <https://webassembly.github.io/spec/core/exec/runtime.html#addresses>
120pub type Addr = u32;
121
122// aliases for clarity
123pub type FuncAddr = Addr;
124pub type TableAddr = Addr;
125pub type MemAddr = Addr;
126pub type GlobalAddr = Addr;
127pub type ElemAddr = Addr;
128pub type DataAddr = Addr;
129pub type ExternAddr = Addr;
130
131// additional internal addresses
132pub type TypeAddr = Addr;
133pub type LocalAddr = u16; // there can't be more than 50.000 locals in a function
134pub type LabelAddr = Addr;
135pub type ModuleInstanceAddr = Addr;
136
137/// A WebAssembly External Value.
138///
139/// See <https://webassembly.github.io/spec/core/exec/runtime.html#external-values>
140#[derive(Debug, Clone)]
141pub enum ExternVal {
142    Func(FuncAddr),
143    Table(TableAddr),
144    Memory(MemAddr),
145    Global(GlobalAddr),
146}
147
148impl ExternVal {
149    #[inline]
150    pub fn kind(&self) -> ExternalKind {
151        match self {
152            Self::Func(_) => ExternalKind::Func,
153            Self::Table(_) => ExternalKind::Table,
154            Self::Memory(_) => ExternalKind::Memory,
155            Self::Global(_) => ExternalKind::Global,
156        }
157    }
158
159    #[inline]
160    pub fn new(kind: ExternalKind, addr: Addr) -> Self {
161        match kind {
162            ExternalKind::Func => Self::Func(addr),
163            ExternalKind::Table => Self::Table(addr),
164            ExternalKind::Memory => Self::Memory(addr),
165            ExternalKind::Global => Self::Global(addr),
166        }
167    }
168}
169
170/// The type of a WebAssembly Function.
171///
172/// See <https://webassembly.github.io/spec/core/syntax/types.html#function-types>
173#[derive(Debug, Clone, PartialEq, Default)]
174#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
175pub struct FuncType {
176    pub params: Box<[ValType]>,
177    pub results: Box<[ValType]>,
178}
179
180#[derive(Debug, Default, Clone, Copy, PartialEq)]
181#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
182pub struct ValueCounts {
183    pub c32: u32,
184    pub c64: u32,
185    pub c128: u32,
186    pub cref: u32,
187}
188
189#[derive(Debug, Default, Clone, Copy, PartialEq)]
190#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
191pub struct ValueCountsSmall {
192    pub c32: u16,
193    pub c64: u16,
194    pub c128: u16,
195    pub cref: u16,
196}
197
198#[derive(Debug, Clone, PartialEq, Default)]
199#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
200pub struct WasmFunction {
201    pub instructions: Box<[Instruction]>,
202    pub locals: ValueCounts,
203    pub params: ValueCountsSmall,
204    pub ty: FuncType,
205}
206
207/// A WebAssembly Module Export
208#[derive(Debug, Clone, PartialEq)]
209#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
210pub struct Export {
211    /// The name of the export.
212    pub name: Box<str>,
213    /// The kind of the export.
214    pub kind: ExternalKind,
215    /// The index of the exported item.
216    pub index: u32,
217}
218
219#[derive(Debug, Clone, PartialEq)]
220#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
221pub struct Global {
222    pub ty: GlobalType,
223    pub init: ConstInstruction,
224}
225
226#[derive(Debug, Clone, Copy, PartialEq)]
227#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
228pub struct GlobalType {
229    pub mutable: bool,
230    pub ty: ValType,
231}
232
233#[derive(Debug, Clone, PartialEq)]
234#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
235pub struct TableType {
236    pub element_type: ValType,
237    pub size_initial: u32,
238    pub size_max: Option<u32>,
239}
240
241impl TableType {
242    pub fn empty() -> Self {
243        Self { element_type: ValType::RefFunc, size_initial: 0, size_max: None }
244    }
245
246    pub fn new(element_type: ValType, size_initial: u32, size_max: Option<u32>) -> Self {
247        Self { element_type, size_initial, size_max }
248    }
249}
250
251/// Represents a memory's type.
252#[derive(Debug, Copy, Clone, PartialEq)]
253#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
254pub struct MemoryType {
255    pub arch: MemoryArch,
256    pub page_count_initial: u64,
257    pub page_count_max: Option<u64>,
258}
259
260impl MemoryType {
261    pub fn new_32(page_count_initial: u64, page_count_max: Option<u64>) -> Self {
262        Self { arch: MemoryArch::I32, page_count_initial, page_count_max }
263    }
264}
265
266#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
267#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
268pub enum MemoryArch {
269    I32,
270    I64,
271}
272
273#[derive(Debug, Clone, PartialEq)]
274#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
275pub struct Import {
276    pub module: Box<str>,
277    pub name: Box<str>,
278    pub kind: ImportKind,
279}
280
281#[derive(Debug, Clone, PartialEq)]
282#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
283pub enum ImportKind {
284    Function(TypeAddr),
285    Table(TableType),
286    Memory(MemoryType),
287    Global(GlobalType),
288}
289
290impl From<&ImportKind> for ExternalKind {
291    #[inline]
292    fn from(kind: &ImportKind) -> Self {
293        match kind {
294            ImportKind::Function(_) => Self::Func,
295            ImportKind::Table(_) => Self::Table,
296            ImportKind::Memory(_) => Self::Memory,
297            ImportKind::Global(_) => Self::Global,
298        }
299    }
300}
301
302#[derive(Debug, Clone, PartialEq)]
303#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
304pub struct Data {
305    pub data: Box<[u8]>,
306    pub range: Range<usize>,
307    pub kind: DataKind,
308}
309
310#[derive(Debug, Clone, PartialEq)]
311#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
312pub enum DataKind {
313    Active { mem: MemAddr, offset: ConstInstruction },
314    Passive,
315}
316
317#[derive(Debug, Clone, PartialEq)]
318#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
319pub struct Element {
320    pub kind: ElementKind,
321    pub items: Box<[ElementItem]>,
322    pub range: Range<usize>,
323    pub ty: ValType,
324}
325
326#[derive(Debug, Clone, Copy, PartialEq)]
327#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
328pub enum ElementKind {
329    Passive,
330    Active { table: TableAddr, offset: ConstInstruction },
331    Declared,
332}
333
334#[derive(Debug, Clone, Copy, PartialEq)]
335#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
336pub enum ElementItem {
337    Func(FuncAddr),
338    Expr(ConstInstruction),
339}