#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_assignments, unused_variables))
))]
#![warn(missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
#![no_std]
#![forbid(unsafe_code)]
extern crate alloc;
use alloc::boxed::Box;
use core::{fmt::Debug, ops::Range};
#[cfg(feature = "logging")]
#[allow(clippy::single_component_path_imports, unused_imports)]
use log;
#[cfg(not(feature = "logging"))]
#[allow(unused_imports, unused_macros)]
pub(crate) mod log {
macro_rules! debug ( ($($tt:tt)*) => {{}} );
macro_rules! info ( ($($tt:tt)*) => {{}} );
macro_rules! error ( ($($tt:tt)*) => {{}} );
pub(crate) use debug;
pub(crate) use error;
pub(crate) use info;
}
mod instructions;
mod value;
pub use instructions::*;
pub use value::*;
#[cfg(feature = "archive")]
pub mod archive;
#[derive(Debug, Clone, Default, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct TinyWasmModule {
pub start_func: Option<FuncAddr>,
pub funcs: Box<[WasmFunction]>,
pub func_types: Box<[FuncType]>,
pub exports: Box<[Export]>,
pub globals: Box<[Global]>,
pub table_types: Box<[TableType]>,
pub memory_types: Box<[MemoryType]>,
pub imports: Box<[Import]>,
pub data: Box<[Data]>,
pub elements: Box<[Element]>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub enum ExternalKind {
Func,
Table,
Memory,
Global,
}
pub type Addr = u32;
pub type FuncAddr = Addr;
pub type TableAddr = Addr;
pub type MemAddr = Addr;
pub type GlobalAddr = Addr;
pub type ElemAddr = Addr;
pub type DataAddr = Addr;
pub type ExternAddr = Addr;
pub type TypeAddr = Addr;
pub type LocalAddr = u16; pub type LabelAddr = Addr;
pub type ModuleInstanceAddr = Addr;
#[derive(Debug, Clone)]
pub enum ExternVal {
Func(FuncAddr),
Table(TableAddr),
Memory(MemAddr),
Global(GlobalAddr),
}
impl ExternVal {
#[inline]
pub fn kind(&self) -> ExternalKind {
match self {
Self::Func(_) => ExternalKind::Func,
Self::Table(_) => ExternalKind::Table,
Self::Memory(_) => ExternalKind::Memory,
Self::Global(_) => ExternalKind::Global,
}
}
#[inline]
pub fn new(kind: ExternalKind, addr: Addr) -> Self {
match kind {
ExternalKind::Func => Self::Func(addr),
ExternalKind::Table => Self::Table(addr),
ExternalKind::Memory => Self::Memory(addr),
ExternalKind::Global => Self::Global(addr),
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct FuncType {
pub params: Box<[ValType]>,
pub results: Box<[ValType]>,
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct ValueCounts {
pub c32: u32,
pub c64: u32,
pub c128: u32,
pub cref: u32,
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct ValueCountsSmall {
pub c32: u16,
pub c64: u16,
pub c128: u16,
pub cref: u16,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct WasmFunction {
pub instructions: Box<[Instruction]>,
pub locals: ValueCounts,
pub params: ValueCountsSmall,
pub ty: FuncType,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct Export {
pub name: Box<str>,
pub kind: ExternalKind,
pub index: u32,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct Global {
pub ty: GlobalType,
pub init: ConstInstruction,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct GlobalType {
pub mutable: bool,
pub ty: ValType,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct TableType {
pub element_type: ValType,
pub size_initial: u32,
pub size_max: Option<u32>,
}
impl TableType {
pub fn empty() -> Self {
Self { element_type: ValType::RefFunc, size_initial: 0, size_max: None }
}
pub fn new(element_type: ValType, size_initial: u32, size_max: Option<u32>) -> Self {
Self { element_type, size_initial, size_max }
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct MemoryType {
pub arch: MemoryArch,
pub page_count_initial: u64,
pub page_count_max: Option<u64>,
}
impl MemoryType {
pub fn new_32(page_count_initial: u64, page_count_max: Option<u64>) -> Self {
Self { arch: MemoryArch::I32, page_count_initial, page_count_max }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub enum MemoryArch {
I32,
I64,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct Import {
pub module: Box<str>,
pub name: Box<str>,
pub kind: ImportKind,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub enum ImportKind {
Function(TypeAddr),
Table(TableType),
Memory(MemoryType),
Global(GlobalType),
}
impl From<&ImportKind> for ExternalKind {
#[inline]
fn from(kind: &ImportKind) -> Self {
match kind {
ImportKind::Function(_) => Self::Func,
ImportKind::Table(_) => Self::Table,
ImportKind::Memory(_) => Self::Memory,
ImportKind::Global(_) => Self::Global,
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct Data {
pub data: Box<[u8]>,
pub range: Range<usize>,
pub kind: DataKind,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub enum DataKind {
Active { mem: MemAddr, offset: ConstInstruction },
Passive,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub struct Element {
pub kind: ElementKind,
pub items: Box<[ElementItem]>,
pub range: Range<usize>,
pub ty: ValType,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub enum ElementKind {
Passive,
Active { table: TableAddr, offset: ConstInstruction },
Declared,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
pub enum ElementItem {
Func(FuncAddr),
Expr(ConstInstruction),
}