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
9extern crate alloc;
12use alloc::boxed::Box;
13use core::{fmt::Debug, ops::Range};
14
15#[cfg(feature = "logging")]
17#[allow(clippy::single_component_path_imports, unused_imports)]
18use log;
19
20#[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#[derive(Debug, Clone, Default, PartialEq)]
46#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
47pub struct TinyWasmModule {
48 pub start_func: Option<FuncAddr>,
52
53 pub funcs: Box<[WasmFunction]>,
57
58 pub func_types: Box<[FuncType]>,
62
63 pub exports: Box<[Export]>,
67
68 pub globals: Box<[Global]>,
72
73 pub table_types: Box<[TableType]>,
77
78 pub memory_types: Box<[MemoryType]>,
82
83 pub imports: Box<[Import]>,
87
88 pub data: Box<[Data]>,
92
93 pub elements: Box<[Element]>,
97}
98
99#[derive(Debug, Clone, Copy, PartialEq)]
103#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
104pub enum ExternalKind {
105 Func,
107 Table,
109 Memory,
111 Global,
113}
114
115pub type Addr = u32;
121
122pub 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
131pub type TypeAddr = Addr;
133pub type LocalAddr = u16; pub type LabelAddr = Addr;
135pub type ModuleInstanceAddr = Addr;
136
137#[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#[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#[derive(Debug, Clone, PartialEq)]
209#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
210pub struct Export {
211 pub name: Box<str>,
213 pub kind: ExternalKind,
215 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#[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}