Files
simple-rust-tests/__wasm/wasmtime-serde-demo/crates/host/src/runtime.rs

69 lines
2.3 KiB
Rust

use crate::*;
use std::{cell::RefCell, rc::Rc};
pub struct Runtime {
instance: wasmtime::Instance,
store: Rc<RefCell<wasmtime::Store<Option<RuntimeCaller>>>>,
}
#[derive(Clone, Copy)]
pub(crate) struct RuntimeCaller {
pub(crate) memory: wasmtime::Memory,
pub(crate) alloc_fn: wasmtime::TypedFunc<u32, u32>,
pub(crate) dealloc_fn: wasmtime::TypedFunc<u64, ()>,
}
impl Runtime {
pub fn from_file(file: impl AsRef<std::path::Path>, imports: &'static [(&'static str, fn(&[u8]) -> Vec<u8>)]) -> anyhow::Result<Self> {
Self::new(&std::fs::read(&file)?, imports)
}
pub fn new(bytes: impl AsRef<[u8]>, imports: &'static [(&'static str, fn(&[u8]) -> Vec<u8>)]) -> anyhow::Result<Self> {
let engine = wasmtime::Engine::default();
let module = wasmtime::Module::new(&engine, bytes)?;
let mut store = wasmtime::Store::new(&engine, None);
let mut linker = wasmtime::Linker::new(&engine);
for (name, callback) in imports {
linker.func_wrap("env", name, |mut caller: wasmtime::Caller<Option<RuntimeCaller>>, ptr: u64| -> u64 {
let RuntimeCaller {
memory,
alloc_fn,
dealloc_fn,
} = caller.data().unwrap();
let (ptr, len) = from_bitwise(ptr);
let mut buffer = vec![0u8; len as _];
memory.read(&caller, ptr as _, &mut buffer).unwrap();
dealloc_fn.call(&mut caller, into_bitwise(ptr, len)).unwrap();
let buffer = (callback)(&buffer);
let ptr = alloc_fn.call(&mut caller, buffer.len() as _).unwrap();
memory.write(&mut caller, ptr as _, &buffer).unwrap();
into_bitwise(ptr, buffer.len() as _)
})?;
}
let instance = linker.instantiate(&mut store, &module)?;
let memory = instance.get_memory(&mut store, "memory").unwrap();
let alloc_fn = instance.get_typed_func(&mut store, "alloc")?;
let dealloc_fn = instance.get_typed_func(&mut store, "dealloc")?;
*store.data_mut() = Some(RuntimeCaller {
memory,
alloc_fn,
dealloc_fn,
});
Ok(Self {
instance,
store: Rc::new(RefCell::new(store)),
})
}
pub fn get_func<P: serde::ser::Serialize, R: serde::de::DeserializeOwned>(&self, name: &str) -> anyhow::Result<Func<P, R>> {
let wasm_fn = self
.instance
.get_typed_func::<u64, u64>(&mut *self.store.borrow_mut(), &format!("_wasm_guest_{name}"))?;
Ok(Func {
wasm_fn,
store: self.store.clone(),
par: std::marker::PhantomData::<P>,
rtn: std::marker::PhantomData::<R>,
})
}
}