62 lines
2.4 KiB
Rust
62 lines
2.4 KiB
Rust
// Copyright (c) 2022 Marceline Cramer
|
|
// SDPX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
//! 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<Box<dyn Backend>> {
|
|
let backend = wasmtime::WasmtimeBackend::new()?;
|
|
Ok(Box::new(backend))
|
|
}
|
|
|
|
/// A WebAssembly runtime backend.
|
|
pub trait Backend {
|
|
fn load_module(&self, module: &[u8]) -> anyhow::Result<Arc<dyn Instance>>;
|
|
}
|
|
|
|
/// 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<u8>) -> u32;
|
|
|
|
fn update(&self, panel_ud: u32, dt: f32);
|
|
|
|
fn draw(&self, panel_ud: u32) -> Vec<DrawCommand>;
|
|
|
|
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<u8>);
|
|
}
|