Add panel_send_message and PanelAbi
This commit is contained in:
parent
a84f11ec4a
commit
14540db59c
|
@ -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>>>,
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -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).
|
||||
|
|
Loading…
Reference in New Issue