//! This module defines backends for WebAssembly execution. //! //! Canary is designed to support multiple WebAssembly runtimes for different //! purposes. Currently, [wasmtime](https://wasmtime.dev) is the only one //! implemented, but in the future, [wasm3](https://github.com/wasm3/wasm3) //! will also be provided. use super::*; pub mod wasmtime; /// Creates the default WebAssembly backend. /// /// Currently, only ever creates [wasmtime::WasmtimeBackend]. pub fn make_default_backend() -> anyhow::Result> { let backend = wasmtime::WasmtimeBackend::new()?; Ok(Box::new(backend)) } /// A WebAssembly runtime backend. pub trait Backend { fn load_module(&self, module: &[u8]) -> anyhow::Result>; } /// An instance of a WebAssembly module. /// /// All self parameters to this trait's functions are immutable, so the /// implementation must provide interior mutability. This allows instances /// to intelligently optimize the execution of their scripts, for example, by /// allowing the execution of multiple ABI calls from multiple threads when /// a script supports the WebAssembly multithreading extension. pub trait Instance { /// Binds script data to a Canary panel. /// /// To "bind" a Canary panel to a Canary script, this function must be /// called. It passes the ID of a panel to the script, plus an /// initialization message, and the script returns an integer as /// userdata. All panel events will be identified to the script with this /// userdata as the first argument. /// /// The intended usecase for this userdata is to contain a pointer. A /// Canary script can allocate some high-level object in memory, and when /// a panel is bound, the script will return a pointer to that object as the /// userdata. Then, when the runtime calls back into the script, the /// userdata will be reinterpreted as a pointer and a method can be called /// on that object in memory. fn bind_panel(&self, panel: PanelId, msg: Vec) -> u32; fn update(&self, panel_ud: u32, dt: f32); fn draw(&self, panel_ud: u32) -> Vec; fn on_resize(&self, panel_ud: u32, new_size: Vec2); fn on_cursor_event(&self, panel_ud: u32, kind: CursorEventKind, at: Vec2); fn on_message(&self, panel_ud: u32, msg: Vec); }