wasm_runtime_layer/
lib.rs

1#![forbid(unsafe_code)]
2#![warn(missing_docs)]
3#![warn(clippy::missing_docs_in_private_items)]
4#![cfg_attr(not(feature = "std"), no_std)]
5
6//! `wasm_runtime_layer` creates a thin abstraction over WebAssembly runtimes, allowing for backend-agnostic host code. The interface is based upon the `wasmtime` and `wasmi` crates, but may be implemented for any runtime.
7//!
8//! ## Usage
9//!
10//! To use this crate, first instantiate a backend runtime. The runtime may be any
11//! value that implements `backend::WasmEngine`. Some runtimes are already implemented as additional crates.
12//! Then, one can create an `Engine` from the backend runtime, and use it to initialize modules and instances:
13//!
14//! ```rust
15//! # use wasm_runtime_layer::*;
16//! // 1. Instantiate a runtime
17//! let engine = Engine::new(wasmi_runtime_layer::Engine::default());
18//! let mut store = Store::new(&engine, ());
19//!
20//! // 2. Create modules and instances, similar to other runtimes
21//! let module_bin = wat::parse_str(
22//!     r#"
23//! (module
24//! (type $t0 (func (param i32) (result i32)))
25//! (func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
26//!     local.get $p0
27//!     i32.const 1
28//!     i32.add))
29//! "#,
30//! )
31//! .unwrap();
32//!
33//! let module = Module::new(&engine, &module_bin).unwrap();
34//! let instance = Instance::new(&mut store, &module, &Imports::default()).unwrap();
35//!
36//! let add_one = instance
37//!     .get_export(&store, "add_one")
38//!     .unwrap()
39//!     .into_func()
40//!     .unwrap();
41//!         
42//! let mut result = [Value::I32(0)];
43//! add_one
44//!     .call(&mut store, &[Value::I32(42)], &mut result)
45//!     .unwrap();
46//!
47//! assert_eq!(result[0], Value::I32(43));
48//! ```
49//!
50//! ## Backends
51//!
52//! * **wasmer_runtime_layer** - Implements the `WasmEngine` trait for wrappers around `wasmer::Engine` instances.
53//! * **wasmtime_runtime_layer** - Implements the `WasmEngine` trait for wrappers around `wasmtime::Engine` instances.
54//! * **wasmi_runtime_layer** - Implements the `WasmEngine` trait for wrappers around `wasmi::Engine` instances.
55//! * **js_wasm_runtime_layer** - Implements a wasm engine targeting the browser's WebAssembly API on `wasm32-unknown-unknown` targets.
56//! * **pyodide-webassembly-runtime-layer** - Implements a wasm engine targeting the browser's WebAssembly API when running as a Python extension module inside Pyodide.
57//!
58//! Contributions for additional backend implementations are welcome!
59//!
60//! ## Testing
61//!
62//! To run the tests for wasmi and wasmtime, run:
63//!
64//! ```sh
65//! cargo test
66//! ```
67//!
68//! For the *wasm32* target, you can use the slower interpreter *wasmi*, or the native JIT accelerated browser backend.
69//!
70//! To test the backends, you need to install [`wasm-pack`](https://github.com/rustwasm/wasm-pack).
71//!
72//! You can then run:
73//! ```sh
74//! wasm-pack test --node
75//! ```
76
77extern crate alloc;
78
79use alloc::{
80    boxed::Box,
81    string::{String, ToString},
82    sync::Arc,
83    vec::Vec,
84};
85use core::{any::Any, fmt};
86
87use anyhow::Result;
88use fxhash::FxBuildHasher;
89use hashbrown::HashMap;
90use ref_cast::RefCast;
91use smallvec::SmallVec;
92
93use crate::backend::*;
94
95/// Provides traits for implementing runtime backends.
96pub mod backend;
97
98/// The default amount of arguments and return values for which to allocate
99/// stack space.
100const DEFAULT_ARGUMENT_SIZE: usize = 4;
101
102/// A vector which allocates up to the default number of arguments on the stack.
103type ArgumentVec<T> = SmallVec<[T; DEFAULT_ARGUMENT_SIZE]>;
104
105/// Type of a value.
106#[derive(Copy, Clone, Debug, PartialEq, Eq)]
107pub enum ValueType {
108    /// 32-bit signed or unsigned integer.
109    I32,
110    /// 64-bit signed or unsigned integer.
111    I64,
112    /// 32-bit floating point number.
113    F32,
114    /// 64-bit floating point number.
115    F64,
116    /// An optional function reference.
117    FuncRef,
118    /// An optional external reference.
119    ExternRef,
120}
121
122impl fmt::Display for ValueType {
123    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124        match self {
125            ValueType::I32 => write!(f, "i32"),
126            ValueType::I64 => write!(f, "i64"),
127            ValueType::F32 => write!(f, "f32"),
128            ValueType::F64 => write!(f, "f64"),
129            ValueType::FuncRef => write!(f, "funcref"),
130            ValueType::ExternRef => write!(f, "externref"),
131        }
132    }
133}
134
135/// The type of a global variable.
136#[derive(Copy, Clone, Debug, PartialEq, Eq)]
137pub struct GlobalType {
138    /// The value type of the global variable.
139    content: ValueType,
140    /// The mutability of the global variable.
141    mutable: bool,
142}
143
144impl GlobalType {
145    /// Creates a new [`GlobalType`] from the given [`ValueType`] and mutability.
146    pub fn new(content: ValueType, mutable: bool) -> Self {
147        Self { content, mutable }
148    }
149
150    /// Returns the [`ValueType`] of the global variable.
151    pub fn content(&self) -> ValueType {
152        self.content
153    }
154
155    /// Returns whether the global variable is mutable.
156    pub fn mutable(&self) -> bool {
157        self.mutable
158    }
159}
160
161/// A descriptor for a [`Table`] instance.
162#[derive(Copy, Clone, Debug, PartialEq, Eq)]
163pub struct TableType {
164    /// The type of values stored in the [`Table`].
165    element: ValueType,
166    /// The minimum number of elements the [`Table`] must have.
167    min: u32,
168    /// The optional maximum number of elements the [`Table`] can have.
169    ///
170    /// If this is `None` then the [`Table`] is not limited in size.
171    max: Option<u32>,
172}
173
174impl TableType {
175    /// Creates a new [`TableType`].
176    ///
177    /// # Panics
178    ///
179    /// If `min` is greater than `max`.
180    pub fn new(element: ValueType, min: u32, max: Option<u32>) -> Self {
181        if let Some(max) = max {
182            assert!(min <= max);
183        }
184        Self { element, min, max }
185    }
186
187    /// Returns the [`ValueType`] of elements stored in the [`Table`].
188    pub fn element(&self) -> ValueType {
189        self.element
190    }
191
192    /// Returns minimum number of elements the [`Table`] must have.
193    pub fn minimum(&self) -> u32 {
194        self.min
195    }
196
197    /// The optional maximum number of elements the [`Table`] can have.
198    ///
199    /// If this returns `None` then the [`Table`] is not limited in size.
200    pub fn maximum(&self) -> Option<u32> {
201        self.max
202    }
203}
204
205/// The memory type of a linear memory.
206#[derive(Copy, Clone, Debug, PartialEq, Eq)]
207pub struct MemoryType {
208    /// The initial amount of pages that a memory should have.
209    initial: u32,
210    /// The maximum amount of pages to which a memory may grow.
211    maximum: Option<u32>,
212}
213
214impl MemoryType {
215    /// Creates a new memory type with initial and optional maximum pages.
216    pub fn new(initial: u32, maximum: Option<u32>) -> Self {
217        Self { initial, maximum }
218    }
219
220    /// Returns the initial pages of the memory type.
221    pub fn initial_pages(self) -> u32 {
222        self.initial
223    }
224
225    /// Returns the maximum pages of the memory type.
226    ///
227    /// # Note
228    ///
229    /// - Returns `None` if there is no limit set.
230    /// - Maximum memory size cannot exceed `65536` pages or 4GiB.
231    pub fn maximum_pages(self) -> Option<u32> {
232        self.maximum
233    }
234}
235
236/// A function type representing a function's parameter and result types.
237///
238/// # Note
239///
240/// Can be cloned cheaply.
241#[derive(Clone)]
242pub struct FuncType {
243    /// The number of function parameters.
244    len_params: usize,
245    /// The ordered and merged parameter and result types of the function type.
246    ///
247    /// # Note
248    ///
249    /// The parameters and results are ordered and merged in a single
250    /// vector starting with parameters in their order and followed
251    /// by results in their order.
252    /// The `len_params` field denotes how many parameters there are in
253    /// the head of the vector before the results.
254    params_results: Arc<[ValueType]>,
255    /// A debug name used for debugging or tracing purposes.
256    name: Option<Arc<str>>,
257}
258
259impl fmt::Debug for FuncType {
260    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
261        f.debug_struct("FuncType")
262            .field("params", &self.params())
263            .field("results", &self.results())
264            .field("name", &self.name)
265            .finish()
266    }
267}
268
269impl PartialEq for FuncType {
270    fn eq(&self, other: &Self) -> bool {
271        self.len_params == other.len_params && self.params_results == other.params_results
272    }
273}
274
275impl Eq for FuncType {}
276
277impl fmt::Display for FuncType {
278    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279        let params = self.params();
280        let results = self.results();
281
282        let mut first = true;
283
284        write!(f, "func(")?;
285        for param in params {
286            if !first {
287                write!(f, ", ")?;
288            } else {
289                first = false;
290            }
291            write!(f, "{param}")?;
292        }
293
294        let mut first = true;
295
296        write!(f, ")")?;
297        for result in results {
298            if !first {
299                first = false;
300                write!(f, ", ")?;
301            } else {
302                write!(f, " -> ")?;
303            }
304            write!(f, "{result}")?;
305        }
306        Ok(())
307    }
308}
309
310impl FuncType {
311    /// Creates a new [`FuncType`].
312    pub fn new<P, R>(params: P, results: R) -> Self
313    where
314        P: IntoIterator<Item = ValueType>,
315        R: IntoIterator<Item = ValueType>,
316    {
317        let mut params_results = params.into_iter().collect::<Vec<_>>();
318        let len_params = params_results.len();
319        params_results.extend(results);
320        Self {
321            params_results: params_results.into(),
322            len_params,
323            name: None,
324        }
325    }
326
327    /// Returns the parameter types of the function type.
328    pub fn params(&self) -> &[ValueType] {
329        &self.params_results[..self.len_params]
330    }
331
332    /// Returns the result types of the function type.
333    pub fn results(&self) -> &[ValueType] {
334        &self.params_results[self.len_params..]
335    }
336
337    /// Set the debug name of the function
338    pub fn with_name(mut self, name: impl Into<Arc<str>>) -> Self {
339        self.name = Some(name.into());
340        self
341    }
342}
343
344/// The type of an [`Extern`] item.
345///
346/// A list of all possible types which can be externally referenced from a WebAssembly module.
347#[derive(Clone, Debug)]
348pub enum ExternType {
349    /// The type of an [`Extern::Global`].
350    Global(GlobalType),
351    /// The type of an [`Extern::Table`].
352    Table(TableType),
353    /// The type of an [`Extern::Memory`].
354    Memory(MemoryType),
355    /// The type of an [`Extern::Func`].
356    Func(FuncType),
357}
358
359impl From<GlobalType> for ExternType {
360    fn from(global: GlobalType) -> Self {
361        Self::Global(global)
362    }
363}
364
365impl From<TableType> for ExternType {
366    fn from(table: TableType) -> Self {
367        Self::Table(table)
368    }
369}
370
371impl From<MemoryType> for ExternType {
372    fn from(memory: MemoryType) -> Self {
373        Self::Memory(memory)
374    }
375}
376
377impl From<FuncType> for ExternType {
378    fn from(func: FuncType) -> Self {
379        Self::Func(func)
380    }
381}
382
383impl ExternType {
384    /// Returns the underlying [`GlobalType`] or `None` if it is of a different type.
385    pub fn global(&self) -> Option<&GlobalType> {
386        match self {
387            Self::Global(ty) => Some(ty),
388            _ => None,
389        }
390    }
391
392    /// Returns the underlying [`TableType`] or `None` if it is of a different type.
393    pub fn table(&self) -> Option<&TableType> {
394        match self {
395            Self::Table(ty) => Some(ty),
396            _ => None,
397        }
398    }
399
400    /// Returns the underlying [`MemoryType`] or `None` if it is of a different type.
401    pub fn memory(&self) -> Option<&MemoryType> {
402        match self {
403            Self::Memory(ty) => Some(ty),
404            _ => None,
405        }
406    }
407
408    /// Returns the underlying [`FuncType`] or `None` if it is of a different type.
409    pub fn func(&self) -> Option<&FuncType> {
410        match self {
411            Self::Func(ty) => Some(ty),
412            _ => None,
413        }
414    }
415
416    /// Return the underlying [`FuncType`] if the types match
417    pub fn try_into_func(self) -> core::result::Result<FuncType, Self> {
418        if let Self::Func(v) = self {
419            Ok(v)
420        } else {
421            Err(self)
422        }
423    }
424
425    /// Return the underlying [`TableType`] if the types match
426    pub fn try_into_table(self) -> Result<TableType, Self> {
427        if let Self::Table(v) = self {
428            Ok(v)
429        } else {
430            Err(self)
431        }
432    }
433
434    /// Return the underlying [`GlobalType`] if the types match
435    pub fn try_into_global(self) -> Result<GlobalType, Self> {
436        if let Self::Global(v) = self {
437            Ok(v)
438        } else {
439            Err(self)
440        }
441    }
442
443    /// Return the underlying [`MemoryType`] if the types match
444    pub fn try_into_memory(self) -> Result<MemoryType, Self> {
445        if let Self::Memory(v) = self {
446            Ok(v)
447        } else {
448            Err(self)
449        }
450    }
451}
452
453/// A descriptor for an exported WebAssembly value of a [`Module`].
454///
455/// This type is primarily accessed from the [`Module::exports`] method and describes
456/// what names are exported from a Wasm [`Module`] and the type of the item that is exported.
457#[derive(Clone, Debug)]
458pub struct ExportType<'module> {
459    /// The name by which the export is known.
460    pub name: &'module str,
461    /// The type of the exported item.
462    pub ty: ExternType,
463}
464
465/// A descriptor for an imported value into a Wasm [`Module`].
466///
467/// This type is primarily accessed from the [`Module::imports`] method.
468/// Each [`ImportType`] describes an import into the Wasm module with the `module/name`
469/// that it is imported from as well as the type of item that is being imported.
470#[derive(Clone, Debug)]
471pub struct ImportType<'module> {
472    /// The module import name.
473    pub module: &'module str,
474    /// The name of the imported item.
475    pub name: &'module str,
476    /// The external item type.
477    pub ty: ExternType,
478}
479
480/// An external item to a WebAssembly module.
481///
482/// This is returned from [`Instance::exports`](crate::Instance::exports)
483/// or [`Instance::get_export`](crate::Instance::get_export).
484#[derive(Clone, Debug)]
485pub enum Extern {
486    /// A WebAssembly global which acts like a [`Cell<T>`] of sorts, supporting `get` and `set` operations.
487    ///
488    /// [`Cell<T>`]: https://doc.rust-lang.org/core/cell/struct.Cell.html
489    Global(Global),
490    /// A WebAssembly table which is an array of funtion references.
491    Table(Table),
492    /// A WebAssembly linear memory.
493    Memory(Memory),
494    /// A WebAssembly function which can be called.
495    Func(Func),
496}
497
498impl Extern {
499    /// Returns the underlying global variable if `self` is a global variable.
500    ///
501    /// Returns `None` otherwise.
502    pub fn into_global(self) -> Option<Global> {
503        if let Self::Global(global) = self {
504            return Some(global);
505        }
506        None
507    }
508
509    /// Returns the underlying table if `self` is a table.
510    ///
511    /// Returns `None` otherwise.
512    pub fn into_table(self) -> Option<Table> {
513        if let Self::Table(table) = self {
514            return Some(table);
515        }
516        None
517    }
518
519    /// Returns the underlying linear memory if `self` is a linear memory.
520    ///
521    /// Returns `None` otherwise.
522    pub fn into_memory(self) -> Option<Memory> {
523        if let Self::Memory(memory) = self {
524            return Some(memory);
525        }
526        None
527    }
528
529    /// Returns the underlying function if `self` is a function.
530    ///
531    /// Returns `None` otherwise.
532    pub fn into_func(self) -> Option<Func> {
533        if let Self::Func(func) = self {
534            return Some(func);
535        }
536        None
537    }
538
539    /// Returns the type associated with this [`Extern`].
540    pub fn ty(&self, ctx: impl AsContext) -> ExternType {
541        match self {
542            Extern::Global(global) => global.ty(ctx).into(),
543            Extern::Table(table) => table.ty(ctx).into(),
544            Extern::Memory(memory) => memory.ty(ctx).into(),
545            Extern::Func(func) => func.ty(ctx).into(),
546        }
547    }
548}
549
550impl<E: WasmEngine> From<&crate::backend::Extern<E>> for Extern {
551    fn from(value: &crate::backend::Extern<E>) -> Self {
552        match value {
553            crate::backend::Extern::Global(x) => Self::Global(Global {
554                global: BackendObject::new(x.clone()),
555            }),
556            crate::backend::Extern::Table(x) => Self::Table(Table {
557                table: BackendObject::new(x.clone()),
558            }),
559            crate::backend::Extern::Memory(x) => Self::Memory(Memory {
560                memory: BackendObject::new(x.clone()),
561            }),
562            crate::backend::Extern::Func(x) => Self::Func(Func {
563                func: BackendObject::new(x.clone()),
564            }),
565        }
566    }
567}
568
569impl<E: WasmEngine> From<&Extern> for crate::backend::Extern<E> {
570    fn from(value: &Extern) -> Self {
571        match value {
572            Extern::Global(x) => Self::Global(x.global.cast::<E::Global>().clone()),
573            Extern::Table(x) => Self::Table(x.table.cast::<E::Table>().clone()),
574            Extern::Memory(x) => Self::Memory(x.memory.cast::<E::Memory>().clone()),
575            Extern::Func(x) => Self::Func(x.func.cast::<E::Func>().clone()),
576        }
577    }
578}
579
580/// A descriptor for an exported WebAssembly value of an [`Instance`].
581///
582/// This type is primarily accessed from the [`Instance::exports`] method and describes
583/// what names are exported from a Wasm [`Instance`] and the type of the item that is exported.
584pub struct Export {
585    /// The name by which the export is known.
586    pub name: String,
587    /// The value of the exported item.
588    pub value: Extern,
589}
590
591impl<E: WasmEngine> From<crate::backend::Export<E>> for Export {
592    fn from(value: crate::backend::Export<E>) -> Self {
593        Self {
594            name: value.name,
595            value: (&value.value).into(),
596        }
597    }
598}
599
600/// All of the import data used when instantiating.
601#[derive(Clone, Debug)]
602pub struct Imports {
603    /// The mapping from names to externals.
604    pub(crate) map: HashMap<(String, String), Extern, FxBuildHasher>,
605}
606
607impl Imports {
608    /// Create a new `Imports`.
609    pub fn new() -> Self {
610        Self {
611            map: HashMap::default(),
612        }
613    }
614
615    /// Gets an export given a module and a name
616    pub fn get_export(&self, module: &str, name: &str) -> Option<Extern> {
617        if self.exists(module, name) {
618            let ext = &self.map[&(module.to_string(), name.to_string())];
619            return Some(ext.clone());
620        }
621        None
622    }
623
624    /// Returns if an export exist for a given module and name.
625    pub fn exists(&self, module: &str, name: &str) -> bool {
626        self.map
627            .contains_key(&(module.to_string(), name.to_string()))
628    }
629
630    /// Returns true if the Imports contains namespace with the provided name.
631    pub fn contains_namespace(&self, name: &str) -> bool {
632        self.map.keys().any(|(k, _)| (k == name))
633    }
634
635    /// Register a list of externs into a namespace.
636    pub fn register_namespace(
637        &mut self,
638        ns: &str,
639        contents: impl IntoIterator<Item = (String, Extern)>,
640    ) {
641        for (name, extern_) in contents.into_iter() {
642            self.map.insert((ns.to_string(), name.clone()), extern_);
643        }
644    }
645
646    /// Add a single import with a namespace `ns` and name `name`.
647    pub fn define(&mut self, ns: &str, name: &str, val: impl Into<Extern>) {
648        self.map
649            .insert((ns.to_string(), name.to_string()), val.into());
650    }
651
652    /// Iterates through all the imports in this structure
653    pub fn iter(&self) -> ImportsIterator {
654        ImportsIterator::new(self)
655    }
656}
657
658/// An iterator over imports.
659pub struct ImportsIterator<'a> {
660    /// The inner iterator over external items.
661    iter: hashbrown::hash_map::Iter<'a, (String, String), Extern>,
662}
663
664impl<'a> ImportsIterator<'a> {
665    /// Creates a new imports iterator.
666    fn new(imports: &'a Imports) -> Self {
667        let iter = imports.map.iter();
668        Self { iter }
669    }
670}
671
672impl<'a> Iterator for ImportsIterator<'a> {
673    type Item = (&'a str, &'a str, &'a Extern);
674
675    fn next(&mut self) -> Option<Self::Item> {
676        self.iter
677            .next()
678            .map(|(k, v)| (k.0.as_str(), k.1.as_str(), v))
679    }
680}
681
682impl IntoIterator for &Imports {
683    type IntoIter = hashbrown::hash_map::IntoIter<(String, String), Extern>;
684    type Item = ((String, String), Extern);
685
686    fn into_iter(self) -> Self::IntoIter {
687        self.map.clone().into_iter()
688    }
689}
690
691impl Default for Imports {
692    fn default() -> Self {
693        Self::new()
694    }
695}
696
697impl Extend<((String, String), Extern)> for Imports {
698    fn extend<T: IntoIterator<Item = ((String, String), Extern)>>(&mut self, iter: T) {
699        for ((ns, name), ext) in iter.into_iter() {
700            self.define(&ns, &name, ext);
701        }
702    }
703}
704
705/// The backing engine for a WebAssembly runtime.
706#[derive(RefCast, Clone)]
707#[repr(transparent)]
708pub struct Engine<E: WasmEngine> {
709    /// The engine backend.
710    backend: E,
711}
712
713impl<E: WasmEngine> Engine<E> {
714    /// Creates a new engine using the specified backend.
715    pub fn new(backend: E) -> Self {
716        Self { backend }
717    }
718
719    /// Unwraps this instance into the core backend engine.
720    pub fn into_backend(self) -> E {
721        self.backend
722    }
723}
724
725/// The store represents all global state that can be manipulated by
726/// WebAssembly programs. It consists of the runtime representation
727/// of all instances of functions, tables, memories, and globals that
728/// have been allocated during the lifetime of the abstract machine.
729///
730/// The `Store` holds the engine (that is —amongst many things— used to compile
731/// the Wasm bytes into a valid module artifact).
732///
733/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#store>
734pub struct Store<T: 'static, E: WasmEngine> {
735    /// The backing implementation.
736    inner: E::Store<T>,
737}
738
739impl<T: 'static, E: WasmEngine> Store<T, E> {
740    /// Creates a new [`Store`] with a specific [`Engine`].
741    pub fn new(engine: &Engine<E>, data: T) -> Self {
742        Self {
743            inner: <E::Store<T> as WasmStore<T, E>>::new(&engine.backend, data),
744        }
745    }
746
747    /// Returns the [`Engine`] that this store is associated with.
748    pub fn engine(&self) -> &Engine<E> {
749        Engine::<E>::ref_cast(self.inner.engine())
750    }
751
752    /// Returns a shared reference to the user provided data owned by this [`Store`].
753    pub fn data(&self) -> &T {
754        self.inner.data()
755    }
756
757    /// Returns an exclusive reference to the user provided data owned by this [`Store`].
758    pub fn data_mut(&mut self) -> &mut T {
759        self.inner.data_mut()
760    }
761
762    /// Consumes `self` and returns its user provided data.
763    pub fn into_data(self) -> T {
764        self.inner.into_data()
765    }
766}
767
768/// A temporary handle to a [`&Store<T>`][`Store`].
769///
770/// This type is suitable for [`AsContext`] trait bounds on methods if desired.
771/// For more information, see [`Store`].
772pub struct StoreContext<'a, T: 'static, E: WasmEngine> {
773    /// The backing implementation.
774    inner: E::StoreContext<'a, T>,
775}
776
777impl<'a, T: 'static, E: WasmEngine> StoreContext<'a, T, E> {
778    /// Returns the underlying [`Engine`] this store is connected to.
779    pub fn engine(&self) -> &Engine<E> {
780        Engine::<E>::ref_cast(self.inner.engine())
781    }
782
783    /// Access the underlying data owned by this store.
784    ///
785    /// Same as [`Store::data`].
786    pub fn data(&self) -> &T {
787        self.inner.data()
788    }
789}
790
791/// A temporary handle to a [`&mut Store<T>`][`Store`].
792///
793/// This type is suitable for [`AsContextMut`] or [`AsContext`] trait bounds on methods if desired.
794/// For more information, see [`Store`].
795pub struct StoreContextMut<'a, T: 'static, E: WasmEngine> {
796    /// The backing implementation.
797    pub inner: E::StoreContextMut<'a, T>,
798}
799
800impl<'a, T: 'static, E: WasmEngine> StoreContextMut<'a, T, E> {
801    /// Returns the underlying [`Engine`] this store is connected to.
802    pub fn engine(&self) -> &Engine<E> {
803        Engine::<E>::ref_cast(self.inner.engine())
804    }
805
806    /// Access the underlying data owned by this store.
807    ///
808    /// Same as [`Store::data`].    
809    pub fn data(&self) -> &T {
810        self.inner.data()
811    }
812
813    /// Access the underlying data owned by this store.
814    ///
815    /// Same as [`Store::data_mut`].
816    pub fn data_mut(&mut self) -> &mut T {
817        self.inner.data_mut()
818    }
819}
820
821/// Runtime representation of a value.
822///
823/// Wasm code manipulate values of the four basic value types:
824/// integers and floating-point data of 32 or 64 bit width each, respectively.
825///
826/// There is no distinction between signed and unsigned integer types. Instead, integers are
827/// interpreted by respective operations as either unsigned or signed in two’s complement representation.
828#[derive(Clone, Debug)]
829pub enum Value {
830    /// Value of 32-bit signed or unsigned integer.
831    I32(i32),
832    /// Value of 64-bit signed or unsigned integer.
833    I64(i64),
834    /// Value of 32-bit floating point number.
835    F32(f32),
836    /// Value of 64-bit floating point number.
837    F64(f64),
838    /// An optional function reference.
839    FuncRef(Option<Func>),
840    /// An optional external reference.
841    ExternRef(Option<ExternRef>),
842}
843
844impl Value {
845    /// Returns the [`ValueType`] for this [`Value`].
846    #[must_use]
847    pub const fn ty(&self) -> ValueType {
848        match self {
849            Value::I32(_) => ValueType::I32,
850            Value::I64(_) => ValueType::I64,
851            Value::F32(_) => ValueType::F32,
852            Value::F64(_) => ValueType::F64,
853            Value::FuncRef(_) => ValueType::FuncRef,
854            Value::ExternRef(_) => ValueType::ExternRef,
855        }
856    }
857}
858
859impl PartialEq for Value {
860    fn eq(&self, o: &Self) -> bool {
861        match (self, o) {
862            (Self::I32(a), Self::I32(b)) => a == b,
863            (Self::I64(a), Self::I64(b)) => a == b,
864            (Self::F32(a), Self::F32(b)) => a == b,
865            (Self::F64(a), Self::F64(b)) => a == b,
866            _ => false,
867        }
868    }
869}
870
871impl<E: WasmEngine> From<&Value> for crate::backend::Value<E> {
872    fn from(value: &Value) -> Self {
873        match value {
874            Value::I32(i32) => Self::I32(*i32),
875            Value::I64(i64) => Self::I64(*i64),
876            Value::F32(f32) => Self::F32(*f32),
877            Value::F64(f64) => Self::F64(*f64),
878            Value::FuncRef(None) => Self::FuncRef(None),
879            Value::FuncRef(Some(func)) => Self::FuncRef(Some(func.func.cast::<E::Func>().clone())),
880            Value::ExternRef(None) => Self::ExternRef(None),
881            Value::ExternRef(Some(extern_ref)) => {
882                Self::ExternRef(Some(extern_ref.extern_ref.cast::<E::ExternRef>().clone()))
883            }
884        }
885    }
886}
887
888impl<E: WasmEngine> From<&backend::Value<E>> for Value {
889    fn from(value: &crate::backend::Value<E>) -> Self {
890        match value {
891            crate::backend::Value::I32(i32) => Self::I32(*i32),
892            crate::backend::Value::I64(i64) => Self::I64(*i64),
893            crate::backend::Value::F32(f32) => Self::F32(*f32),
894            crate::backend::Value::F64(f64) => Self::F64(*f64),
895            crate::backend::Value::FuncRef(None) => Self::FuncRef(None),
896            crate::backend::Value::FuncRef(Some(func)) => Self::FuncRef(Some(Func {
897                func: BackendObject::new(func.clone()),
898            })),
899            crate::backend::Value::ExternRef(None) => Self::ExternRef(None),
900            crate::backend::Value::ExternRef(Some(extern_ref)) => {
901                Self::ExternRef(Some(ExternRef {
902                    extern_ref: BackendObject::new(extern_ref.clone()),
903                }))
904            }
905        }
906    }
907}
908
909/// Represents an opaque reference to any data within WebAssembly.
910#[derive(Clone, Debug)]
911pub struct ExternRef {
912    /// The backing implementation.
913    extern_ref: BackendObject,
914}
915
916impl ExternRef {
917    /// Creates a new [`ExternRef`] wrapping the given value.
918    pub fn new<T: 'static + Send + Sync, C: AsContextMut>(mut ctx: C, object: T) -> Self {
919        Self {
920            extern_ref: BackendObject::new(
921                <<C::Engine as WasmEngine>::ExternRef as WasmExternRef<C::Engine>>::new(
922                    ctx.as_context_mut().inner,
923                    object,
924                ),
925            ),
926        }
927    }
928
929    /// Returns a shared reference to the underlying data for this [`ExternRef`].
930    pub fn downcast<'a, 's: 'a, T: 'static, S: 'static, E: WasmEngine>(
931        &'a self,
932        ctx: StoreContext<'s, S, E>,
933    ) -> Result<&'a T> {
934        self.extern_ref.cast::<E::ExternRef>().downcast(ctx.inner)
935    }
936}
937
938/// A Wasm or host function reference.
939#[derive(Clone, Debug)]
940pub struct Func {
941    /// The backing implementation.
942    func: BackendObject,
943}
944
945impl Func {
946    /// Creates a new [`Func`] with the given arguments.
947    pub fn new<C: AsContextMut>(
948        mut ctx: C,
949        ty: FuncType,
950        func: impl 'static
951            + Send
952            + Sync
953            + Fn(StoreContextMut<'_, C::UserState, C::Engine>, &[Value], &mut [Value]) -> Result<()>,
954    ) -> Self {
955        let raw_func = <<C::Engine as WasmEngine>::Func as WasmFunc<C::Engine>>::new(
956            ctx.as_context_mut().inner,
957            ty,
958            move |ctx, args, results| {
959                let mut input = ArgumentVec::with_capacity(args.len());
960                input.extend(args.iter().map(Into::into));
961
962                let mut output = ArgumentVec::with_capacity(results.len());
963                output.extend(results.iter().map(Into::into));
964
965                func(StoreContextMut { inner: ctx }, &input, &mut output)?;
966
967                for (i, result) in output.iter().enumerate() {
968                    results[i] = result.into();
969                }
970
971                Ok(())
972            },
973        );
974
975        Self {
976            func: BackendObject::new(raw_func),
977        }
978    }
979
980    /// Returns the function type of the [`Func`].
981    pub fn ty<C: AsContext>(&self, ctx: C) -> FuncType {
982        self.func
983            .cast::<<C::Engine as WasmEngine>::Func>()
984            .ty(ctx.as_context().inner)
985    }
986
987    /// Calls the Wasm or host function with the given inputs.
988    ///
989    /// The result is written back into the `outputs` buffer.
990    pub fn call<C: AsContextMut>(
991        &self,
992        mut ctx: C,
993        args: &[Value],
994        results: &mut [Value],
995    ) -> Result<()> {
996        let raw_func = self.func.cast::<<C::Engine as WasmEngine>::Func>();
997
998        let mut input = ArgumentVec::with_capacity(args.len());
999        input.extend(args.iter().map(Into::into));
1000
1001        let mut output = ArgumentVec::with_capacity(results.len());
1002        output.extend(results.iter().map(Into::into));
1003
1004        raw_func.call::<C::UserState>(ctx.as_context_mut().inner, &input, &mut output)?;
1005
1006        for (i, result) in output.iter().enumerate() {
1007            results[i] = result.into();
1008        }
1009
1010        Ok(())
1011    }
1012}
1013
1014/// A Wasm global variable reference.
1015#[derive(Clone, Debug)]
1016pub struct Global {
1017    /// The backing implementation.
1018    global: BackendObject,
1019}
1020
1021impl Global {
1022    /// Creates a new global variable to the store.
1023    pub fn new<C: AsContextMut>(mut ctx: C, initial_value: Value, mutable: bool) -> Self {
1024        Self {
1025            global: BackendObject::new(<<C::Engine as WasmEngine>::Global as WasmGlobal<
1026                C::Engine,
1027            >>::new(
1028                ctx.as_context_mut().inner,
1029                (&initial_value).into(),
1030                mutable,
1031            )),
1032        }
1033    }
1034
1035    /// Returns the [`GlobalType`] of the global variable.
1036    pub fn ty<C: AsContext>(&self, ctx: C) -> GlobalType {
1037        self.global
1038            .cast::<<C::Engine as WasmEngine>::Global>()
1039            .ty(ctx.as_context().inner)
1040    }
1041
1042    /// Returns the current value of the global variable.
1043    pub fn get<C: AsContextMut>(&self, mut ctx: C) -> Value {
1044        (&self
1045            .global
1046            .cast::<<C::Engine as WasmEngine>::Global>()
1047            .get(ctx.as_context_mut().inner))
1048            .into()
1049    }
1050
1051    /// Sets a new value to the global variable.
1052    pub fn set<C: AsContextMut>(&self, mut ctx: C, new_value: Value) -> Result<()> {
1053        self.global
1054            .cast::<<C::Engine as WasmEngine>::Global>()
1055            .set(ctx.as_context_mut().inner, (&new_value).into())
1056    }
1057}
1058
1059/// A parsed and validated WebAssembly module.
1060#[derive(Clone, Debug)]
1061pub struct Module {
1062    /// The backing implementation.
1063    module: BackendObject,
1064}
1065
1066impl Module {
1067    /// Creates a new Wasm [`Module`] from the given byte slice.
1068    pub fn new<E: WasmEngine>(engine: &Engine<E>, bytes: &[u8]) -> Result<Self> {
1069        Ok(Self {
1070            module: BackendObject::new(<E::Module as WasmModule<E>>::new(&engine.backend, bytes)?),
1071        })
1072    }
1073
1074    /// Returns an iterator over the exports of the [`Module`].
1075    pub fn exports<E: WasmEngine>(
1076        &self,
1077        #[allow(unused_variables)] engine: &Engine<E>,
1078    ) -> impl '_ + Iterator<Item = ExportType<'_>> {
1079        self.module.cast::<E::Module>().exports()
1080    }
1081
1082    /// Looks up an export in this [`Module`] by its `name`.
1083    ///
1084    /// Returns `None` if no export with the name was found.
1085    pub fn get_export<E: WasmEngine>(
1086        &self,
1087        #[allow(unused_variables)] engine: &Engine<E>,
1088        name: &str,
1089    ) -> Option<ExternType> {
1090        self.module.cast::<E::Module>().get_export(name)
1091    }
1092
1093    /// Returns an iterator over the imports of the [`Module`].
1094    pub fn imports<E: WasmEngine>(
1095        &self,
1096        #[allow(unused_variables)] engine: &Engine<E>,
1097    ) -> impl '_ + Iterator<Item = ImportType<'_>> {
1098        self.module.cast::<E::Module>().imports()
1099    }
1100}
1101
1102/// An instantiated WebAssembly [`Module`].
1103///
1104/// This type represents an instantiation of a [`Module`].
1105/// It primarily allows to access its [`exports`](Instance::exports)
1106/// to call functions, get or set globals, read or write memory, etc.
1107///
1108/// When interacting with any Wasm code you will want to create an
1109/// [`Instance`] in order to execute anything.
1110#[derive(Clone, Debug)]
1111pub struct Instance {
1112    /// The backing implementation.
1113    instance: BackendObject,
1114}
1115
1116impl Instance {
1117    /// Creates a new [`Instance`] which runs code from the provided module against the given import set.
1118    pub fn new<C: AsContextMut>(mut ctx: C, module: &Module, imports: &Imports) -> Result<Self> {
1119        let mut backend_imports = crate::backend::Imports::default();
1120        backend_imports.extend(
1121            imports
1122                .into_iter()
1123                .map(|((host, name), val)| ((host, name), (&val).into())),
1124        );
1125
1126        Ok(Self {
1127            instance: BackendObject::new(<<C::Engine as WasmEngine>::Instance as WasmInstance<
1128                C::Engine,
1129            >>::new(
1130                ctx.as_context_mut().inner,
1131                module.module.cast(),
1132                &backend_imports,
1133            )?),
1134        })
1135    }
1136
1137    /// Returns an iterator over the exports of the [`Instance`].
1138    pub fn exports<C: AsContext>(&self, ctx: C) -> impl Iterator<Item = Export> {
1139        let instance = self.instance.cast::<<C::Engine as WasmEngine>::Instance>();
1140
1141        <_ as WasmInstance<_>>::exports(instance, ctx.as_context().inner).map(Into::into)
1142    }
1143
1144    /// Returns the value exported to the given `name` if any.
1145    pub fn get_export<C: AsContext>(&self, ctx: C, name: &str) -> Option<Extern> {
1146        let instance = self.instance.cast::<<C::Engine as WasmEngine>::Instance>();
1147
1148        <_ as WasmInstance<_>>::get_export(instance, ctx.as_context().inner, name)
1149            .as_ref()
1150            .map(Into::into)
1151    }
1152}
1153
1154/// A Wasm linear memory reference.
1155#[derive(Clone, Debug)]
1156pub struct Memory {
1157    /// The backing implementation.
1158    memory: BackendObject,
1159}
1160
1161impl Memory {
1162    /// Creates a new linear memory to the store.
1163    pub fn new<C: AsContextMut>(mut ctx: C, ty: MemoryType) -> Result<Self> {
1164        Ok(Self {
1165            memory: BackendObject::new(<<C::Engine as WasmEngine>::Memory as WasmMemory<
1166                C::Engine,
1167            >>::new(ctx.as_context_mut().inner, ty)?),
1168        })
1169    }
1170
1171    /// Returns the memory type of the linear memory.
1172    pub fn ty<C: AsContext>(&self, ctx: C) -> MemoryType {
1173        self.memory
1174            .cast::<<C::Engine as WasmEngine>::Memory>()
1175            .ty(ctx.as_context().inner)
1176    }
1177
1178    /// Grows the linear memory by the given amount of new pages.
1179    pub fn grow<C: AsContextMut>(&self, mut ctx: C, additional: u32) -> Result<u32> {
1180        self.memory
1181            .cast::<<C::Engine as WasmEngine>::Memory>()
1182            .grow(ctx.as_context_mut().inner, additional)
1183    }
1184
1185    /// Returns the amount of pages in use by the linear memory.
1186    pub fn current_pages<C: AsContext>(&self, ctx: C) -> u32 {
1187        self.memory
1188            .cast::<<C::Engine as WasmEngine>::Memory>()
1189            .current_pages(ctx.as_context().inner)
1190    }
1191
1192    /// Reads `n` bytes from `memory[offset..offset+n]` into `buffer`
1193    /// where `n` is the length of `buffer`.
1194    pub fn read<C: AsContext>(&self, ctx: C, offset: usize, buffer: &mut [u8]) -> Result<()> {
1195        self.memory
1196            .cast::<<C::Engine as WasmEngine>::Memory>()
1197            .read(ctx.as_context().inner, offset, buffer)
1198    }
1199
1200    /// Writes `n` bytes to `memory[offset..offset+n]` from `buffer`
1201    /// where `n` if the length of `buffer`.
1202    pub fn write<C: AsContextMut>(&self, mut ctx: C, offset: usize, buffer: &[u8]) -> Result<()> {
1203        self.memory
1204            .cast::<<C::Engine as WasmEngine>::Memory>()
1205            .write(ctx.as_context_mut().inner, offset, buffer)
1206    }
1207}
1208
1209/// A Wasm table reference.
1210#[derive(Clone, Debug)]
1211pub struct Table {
1212    /// The backing implementation.
1213    table: BackendObject,
1214}
1215
1216impl Table {
1217    /// Creates a new table to the store.
1218    pub fn new<C: AsContextMut>(mut ctx: C, ty: TableType, init: Value) -> Result<Self> {
1219        Ok(Self {
1220            table: BackendObject::new(<<C::Engine as WasmEngine>::Table as WasmTable<
1221                C::Engine,
1222            >>::new(
1223                ctx.as_context_mut().inner, ty, (&init).into()
1224            )?),
1225        })
1226    }
1227
1228    /// Returns the type and limits of the table.
1229    pub fn ty<C: AsContext>(&self, ctx: C) -> TableType {
1230        self.table
1231            .cast::<<C::Engine as WasmEngine>::Table>()
1232            .ty(ctx.as_context().inner)
1233    }
1234
1235    /// Returns the current size of the [`Table`].
1236    pub fn size<C: AsContext>(&self, ctx: C) -> u32 {
1237        self.table
1238            .cast::<<C::Engine as WasmEngine>::Table>()
1239            .size(ctx.as_context().inner)
1240    }
1241
1242    /// Grows the table by the given amount of elements.
1243    ///
1244    /// Returns the old size of the [`Table`] upon success.
1245    pub fn grow<C: AsContextMut>(&self, mut ctx: C, delta: u32, init: Value) -> Result<u32> {
1246        let table = self.table.cast::<<C::Engine as WasmEngine>::Table>();
1247
1248        <_ as WasmTable<_>>::grow(table, ctx.as_context_mut().inner, delta, (&init).into())
1249    }
1250
1251    /// Returns the [`Table`] element value at `index`.
1252    ///
1253    /// Returns `None` if `index` is out of bounds.
1254    pub fn get<C: AsContextMut>(&self, mut ctx: C, index: u32) -> Option<Value> {
1255        let table = self.table.cast::<<C::Engine as WasmEngine>::Table>();
1256
1257        <_ as WasmTable<_>>::get(table, ctx.as_context_mut().inner, index)
1258            .as_ref()
1259            .map(Into::into)
1260    }
1261
1262    /// Sets the [`Value`] of this [`Table`] at `index`.
1263    pub fn set<C: AsContextMut>(&self, mut ctx: C, index: u32, value: Value) -> Result<()> {
1264        let table = self.table.cast::<<C::Engine as WasmEngine>::Table>();
1265
1266        <_ as WasmTable<_>>::set(table, ctx.as_context_mut().inner, index, (&value).into())
1267    }
1268}
1269
1270/// A type-erased object that corresponds to an item from a WebAssembly backend runtime.
1271struct BackendObject {
1272    /// The backing implementation.
1273    inner: Box<dyn AnyCloneBoxed>,
1274}
1275
1276impl BackendObject {
1277    /// Creates a new backend object that wraps the given value.
1278    pub fn new<T: 'static + Clone + Send + Sync>(value: T) -> Self {
1279        Self {
1280            inner: Box::new(value),
1281        }
1282    }
1283
1284    /// Casts this backend object to the provided type, or panics if the types conflicted.
1285    pub fn cast<T: 'static>(&self) -> &T {
1286        self.inner
1287            .as_any()
1288            .downcast_ref()
1289            .expect("Attempted to use incorrect context to access function.")
1290    }
1291}
1292
1293impl Clone for BackendObject {
1294    fn clone(&self) -> Self {
1295        Self {
1296            inner: self.inner.clone_boxed(),
1297        }
1298    }
1299}
1300
1301impl fmt::Debug for BackendObject {
1302    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1303        f.debug_struct("BackendObject").finish()
1304    }
1305}
1306
1307/// Marks a type that can be cloned into a box and interpreted as an [`Any`](std::any::Any).
1308trait AnyCloneBoxed: Any + Send + Sync {
1309    /// Gets this type as an [`Any`](std::any::Any).
1310    fn as_any(&self) -> &(dyn Any + Send + Sync);
1311
1312    /// Creates a clone of this type into a new box.
1313    fn clone_boxed(&self) -> Box<dyn AnyCloneBoxed>;
1314}
1315
1316impl<T: Any + Clone + Send + Sync> AnyCloneBoxed for T {
1317    fn as_any(&self) -> &(dyn Any + Send + Sync) {
1318        self
1319    }
1320
1321    fn clone_boxed(&self) -> Box<dyn AnyCloneBoxed> {
1322        Box::new(self.clone())
1323    }
1324}
1325
1326/// A trait used to get shared access to a [`Store`].
1327pub trait AsContext {
1328    /// The engine type associated with the context.
1329    type Engine: WasmEngine;
1330
1331    /// The user state associated with the [`Store`], aka the `T` in `Store<T>`.
1332    type UserState: 'static;
1333
1334    /// Returns the store context that this type provides access to.
1335    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine>;
1336}
1337
1338/// A trait used to get exclusive access to a [`Store`].
1339pub trait AsContextMut: AsContext {
1340    /// Returns the store context that this type provides access to.
1341    fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine>;
1342}
1343
1344impl<T: 'static, E: WasmEngine> AsContext for Store<T, E> {
1345    type Engine = E;
1346
1347    type UserState = T;
1348
1349    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1350        StoreContext {
1351            inner: crate::backend::AsContext::as_context(&self.inner),
1352        }
1353    }
1354}
1355
1356impl<T: 'static, E: WasmEngine> AsContextMut for Store<T, E> {
1357    fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine> {
1358        StoreContextMut {
1359            inner: crate::backend::AsContextMut::as_context_mut(&mut self.inner),
1360        }
1361    }
1362}
1363
1364impl<T: AsContext> AsContext for &T {
1365    type Engine = T::Engine;
1366
1367    type UserState = T::UserState;
1368
1369    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1370        (**self).as_context()
1371    }
1372}
1373
1374impl<T: AsContext> AsContext for &mut T {
1375    type Engine = T::Engine;
1376
1377    type UserState = T::UserState;
1378
1379    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1380        (**self).as_context()
1381    }
1382}
1383
1384impl<T: AsContextMut> AsContextMut for &mut T {
1385    fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine> {
1386        (**self).as_context_mut()
1387    }
1388}
1389
1390impl<'a, T: 'static, E: WasmEngine> AsContext for StoreContext<'a, T, E> {
1391    type Engine = E;
1392
1393    type UserState = T;
1394
1395    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1396        StoreContext {
1397            inner: crate::backend::AsContext::as_context(&self.inner),
1398        }
1399    }
1400}
1401
1402impl<'a, T: 'static, E: WasmEngine> AsContext for StoreContextMut<'a, T, E> {
1403    type Engine = E;
1404
1405    type UserState = T;
1406
1407    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
1408        StoreContext {
1409            inner: crate::backend::AsContext::as_context(&self.inner),
1410        }
1411    }
1412}
1413
1414impl<'a, T: 'static, E: WasmEngine> AsContextMut for StoreContextMut<'a, T, E> {
1415    fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine> {
1416        StoreContextMut {
1417            inner: crate::backend::AsContextMut::as_context_mut(&mut self.inner),
1418        }
1419    }
1420}