Add panel_send_message and PanelAbi

This commit is contained in:
mars 2022-11-16 21:08:17 -07:00
parent a84f11ec4a
commit 14540db59c
3 changed files with 54 additions and 10 deletions

View File

@ -8,6 +8,8 @@
//! implemented, but in the future, [wasm3](https://github.com/wasm3/wasm3)
//! will also be provided.
use std::collections::VecDeque;
use super::*;
pub mod wasmtime;
@ -22,7 +24,7 @@ pub fn make_default_backend() -> anyhow::Result<Box<dyn Backend>> {
/// A WebAssembly runtime backend.
pub trait Backend {
fn load_module(&self, abi: ScriptAbi, module: &[u8]) -> anyhow::Result<Arc<dyn Instance>>;
fn load_module(&self, abi: Arc<ScriptAbi>, module: &[u8]) -> anyhow::Result<Arc<dyn Instance>>;
}
/// An instance of a WebAssembly module.
@ -69,6 +71,7 @@ pub struct ScriptAbi {
loaded_fonts: RwLock<Vec<Arc<text::Font>>>,
text_layouts: RwLock<Slab<text::TextLayout>>,
message_store: RwLock<Slab<Vec<u8>>>,
panels: RwLock<Slab<PanelAbi>>,
}
impl ScriptAbi {
@ -79,6 +82,13 @@ impl ScriptAbi {
}
}
/// Allocates a new ID and host-side storage for a panel.
pub fn create_panel(&self) -> PanelId {
let abi = PanelAbi::default();
let id = self.panels.write().insert(abi);
PanelId(id)
}
pub fn start_draw(&self) {
let mut lock = self.draw_cmds.lock();
lock.clear();
@ -157,4 +167,23 @@ impl ScriptAbi {
let src = store.get(id as usize).unwrap();
dst.copy_from_slice(src);
}
pub fn panel_send_message(&self, id: u32, message: Vec<u8>) {
if let Some(panel) = self.panels.read().get(id as usize) {
panel.outgoing_messages.write().push_back(message);
}
}
pub fn recv_panel_messages(&self, id: PanelId) -> Vec<Vec<u8>> {
if let Some(panel) = self.panels.read().get(id.0) {
panel.outgoing_messages.write().drain(..).collect()
} else {
Vec::new()
}
}
}
#[derive(Default)]
pub struct PanelAbi {
outgoing_messages: RwLock<VecDeque<Vec<u8>>>,
}

View File

@ -9,9 +9,9 @@ use crate::DrawCommand;
use canary_script::{Color, CursorEventKind, Rect, Vec2};
use parking_lot::Mutex;
type Caller<'a> = wasmtime::Caller<'a, ScriptAbi>;
type Store = wasmtime::Store<ScriptAbi>;
type Linker = wasmtime::Linker<ScriptAbi>;
type Caller<'a> = wasmtime::Caller<'a, Arc<ScriptAbi>>;
type Store = wasmtime::Store<Arc<ScriptAbi>>;
type Linker = wasmtime::Linker<Arc<ScriptAbi>>;
pub struct WasmtimeBackend {
engine: wasmtime::Engine,
@ -30,7 +30,7 @@ impl WasmtimeBackend {
}
impl Backend for WasmtimeBackend {
fn load_module(&self, abi: ScriptAbi, module: &[u8]) -> anyhow::Result<Arc<dyn Instance>> {
fn load_module(&self, abi: Arc<ScriptAbi>, module: &[u8]) -> anyhow::Result<Arc<dyn Instance>> {
let module = wasmtime::Module::new(&self.engine, module)?;
let mut store = wasmtime::Store::new(&self.engine, abi);
let mut linker = Linker::new(&self.engine);
@ -147,6 +147,15 @@ impl WasmtimeInstance {
},
)?;
linker.func_wrap(
module,
"panel_send_message",
|mut caller: Caller<'_>, id: u32, ptr: u32, len: u32| {
let message = Self::get_memory_slice_bytes(&mut caller, ptr as usize, len as usize);
caller.data().panel_send_message(id, message.to_vec())
},
)?;
Ok(())
}

View File

@ -29,11 +29,12 @@ impl Runtime {
pub fn load_module(&self, module: &[u8]) -> anyhow::Result<Script> {
let abi = ScriptAbi::new(self.font_store.to_owned());
let instance = self.backend.load_module(abi, module)?;
let abi = Arc::new(abi);
let instance = self.backend.load_module(abi.to_owned(), module)?;
Ok(Script {
instance,
next_panel: 0,
abi,
})
}
}
@ -41,16 +42,16 @@ impl Runtime {
/// A loaded instance of a Canary script.
pub struct Script {
instance: Arc<dyn Instance>,
next_panel: usize,
abi: Arc<ScriptAbi>,
}
impl Script {
pub fn create_panel(&mut self, protocol: &str, msg: Vec<u8>) -> anyhow::Result<Panel> {
let id = PanelId(self.next_panel);
self.next_panel += 1;
let id = self.abi.create_panel();
let userdata = self.instance.bind_panel(id, protocol, msg);
Ok(Panel {
instance: self.instance.clone(),
abi: self.abi.clone(),
id,
userdata,
})
@ -60,6 +61,7 @@ impl Script {
/// A Canary panel.
pub struct Panel {
instance: Arc<dyn Instance>,
abi: Arc<ScriptAbi>,
id: PanelId,
userdata: u32,
}
@ -84,6 +86,10 @@ impl Panel {
pub fn on_message(&self, msg: Vec<u8>) {
self.instance.on_message(self.userdata, msg);
}
pub fn recv_messages(&self) -> Vec<Vec<u8>> {
self.abi.recv_panel_messages(self.id)
}
}
/// Proportion constant between pixels (at 96dpi) to millimeters (Canary's unit measurement).