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)
|
//! implemented, but in the future, [wasm3](https://github.com/wasm3/wasm3)
|
||||||
//! will also be provided.
|
//! will also be provided.
|
||||||
|
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub mod wasmtime;
|
pub mod wasmtime;
|
||||||
|
@ -22,7 +24,7 @@ pub fn make_default_backend() -> anyhow::Result<Box<dyn Backend>> {
|
||||||
|
|
||||||
/// A WebAssembly runtime backend.
|
/// A WebAssembly runtime backend.
|
||||||
pub trait 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.
|
/// An instance of a WebAssembly module.
|
||||||
|
@ -69,6 +71,7 @@ pub struct ScriptAbi {
|
||||||
loaded_fonts: RwLock<Vec<Arc<text::Font>>>,
|
loaded_fonts: RwLock<Vec<Arc<text::Font>>>,
|
||||||
text_layouts: RwLock<Slab<text::TextLayout>>,
|
text_layouts: RwLock<Slab<text::TextLayout>>,
|
||||||
message_store: RwLock<Slab<Vec<u8>>>,
|
message_store: RwLock<Slab<Vec<u8>>>,
|
||||||
|
panels: RwLock<Slab<PanelAbi>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScriptAbi {
|
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) {
|
pub fn start_draw(&self) {
|
||||||
let mut lock = self.draw_cmds.lock();
|
let mut lock = self.draw_cmds.lock();
|
||||||
lock.clear();
|
lock.clear();
|
||||||
|
@ -157,4 +167,23 @@ impl ScriptAbi {
|
||||||
let src = store.get(id as usize).unwrap();
|
let src = store.get(id as usize).unwrap();
|
||||||
dst.copy_from_slice(src);
|
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 canary_script::{Color, CursorEventKind, Rect, Vec2};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
type Caller<'a> = wasmtime::Caller<'a, ScriptAbi>;
|
type Caller<'a> = wasmtime::Caller<'a, Arc<ScriptAbi>>;
|
||||||
type Store = wasmtime::Store<ScriptAbi>;
|
type Store = wasmtime::Store<Arc<ScriptAbi>>;
|
||||||
type Linker = wasmtime::Linker<ScriptAbi>;
|
type Linker = wasmtime::Linker<Arc<ScriptAbi>>;
|
||||||
|
|
||||||
pub struct WasmtimeBackend {
|
pub struct WasmtimeBackend {
|
||||||
engine: wasmtime::Engine,
|
engine: wasmtime::Engine,
|
||||||
|
@ -30,7 +30,7 @@ impl WasmtimeBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend for 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 module = wasmtime::Module::new(&self.engine, module)?;
|
||||||
let mut store = wasmtime::Store::new(&self.engine, abi);
|
let mut store = wasmtime::Store::new(&self.engine, abi);
|
||||||
let mut linker = Linker::new(&self.engine);
|
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(())
|
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> {
|
pub fn load_module(&self, module: &[u8]) -> anyhow::Result<Script> {
|
||||||
let abi = ScriptAbi::new(self.font_store.to_owned());
|
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 {
|
Ok(Script {
|
||||||
instance,
|
instance,
|
||||||
next_panel: 0,
|
abi,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,16 +42,16 @@ impl Runtime {
|
||||||
/// A loaded instance of a Canary script.
|
/// A loaded instance of a Canary script.
|
||||||
pub struct Script {
|
pub struct Script {
|
||||||
instance: Arc<dyn Instance>,
|
instance: Arc<dyn Instance>,
|
||||||
next_panel: usize,
|
abi: Arc<ScriptAbi>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Script {
|
impl Script {
|
||||||
pub fn create_panel(&mut self, protocol: &str, msg: Vec<u8>) -> anyhow::Result<Panel> {
|
pub fn create_panel(&mut self, protocol: &str, msg: Vec<u8>) -> anyhow::Result<Panel> {
|
||||||
let id = PanelId(self.next_panel);
|
let id = self.abi.create_panel();
|
||||||
self.next_panel += 1;
|
|
||||||
let userdata = self.instance.bind_panel(id, protocol, msg);
|
let userdata = self.instance.bind_panel(id, protocol, msg);
|
||||||
Ok(Panel {
|
Ok(Panel {
|
||||||
instance: self.instance.clone(),
|
instance: self.instance.clone(),
|
||||||
|
abi: self.abi.clone(),
|
||||||
id,
|
id,
|
||||||
userdata,
|
userdata,
|
||||||
})
|
})
|
||||||
|
@ -60,6 +61,7 @@ impl Script {
|
||||||
/// A Canary panel.
|
/// A Canary panel.
|
||||||
pub struct Panel {
|
pub struct Panel {
|
||||||
instance: Arc<dyn Instance>,
|
instance: Arc<dyn Instance>,
|
||||||
|
abi: Arc<ScriptAbi>,
|
||||||
id: PanelId,
|
id: PanelId,
|
||||||
userdata: u32,
|
userdata: u32,
|
||||||
}
|
}
|
||||||
|
@ -84,6 +86,10 @@ impl Panel {
|
||||||
pub fn on_message(&self, msg: Vec<u8>) {
|
pub fn on_message(&self, msg: Vec<u8>) {
|
||||||
self.instance.on_message(self.userdata, msg);
|
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).
|
/// Proportion constant between pixels (at 96dpi) to millimeters (Canary's unit measurement).
|
||||||
|
|
Loading…
Reference in New Issue