use std::path::Path;
use std::sync::Arc;
pub use wasmtime;
#[derive(Clone)]
pub struct WasmBench {
inner: Arc<Inner>,
}
struct Inner {
engine: wasmtime::Engine,
module: wasmtime::Module,
}
pub struct WasmInstance {
pub store: wasmtime::Store<wasmtime_wasi::p1::WasiP1Ctx>,
instance: wasmtime::Instance,
}
impl WasmBench {
pub fn from_wat(wat: &str) -> Result<Self, wasmtime::Error> {
Self::from_bytes(wat.as_bytes())
}
pub fn from_file(path: impl AsRef<Path>) -> Result<Self, wasmtime::Error> {
let engine = Self::make_engine()?;
let module = wasmtime::Module::from_file(&engine, path.as_ref())?;
Ok(Self {
inner: Arc::new(Inner { engine, module }),
})
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, wasmtime::Error> {
let engine = Self::make_engine()?;
let module = wasmtime::Module::new(&engine, bytes)?;
Ok(Self {
inner: Arc::new(Inner { engine, module }),
})
}
pub fn from_bytes_with_config(
bytes: &[u8],
config: wasmtime::Config,
) -> Result<Self, wasmtime::Error> {
let engine = wasmtime::Engine::new(&config)?;
let module = wasmtime::Module::new(&engine, bytes)?;
Ok(Self {
inner: Arc::new(Inner { engine, module }),
})
}
fn make_engine() -> Result<wasmtime::Engine, wasmtime::Error> {
let mut config = wasmtime::Config::new();
config.wasm_simd(true);
config.cranelift_opt_level(wasmtime::OptLevel::Speed);
wasmtime::Engine::new(&config)
}
fn make_p1_ctx() -> wasmtime_wasi::p1::WasiP1Ctx {
wasmtime_wasi::WasiCtxBuilder::new().build_p1()
}
pub fn instance(&self) -> Result<WasmInstance, wasmtime::Error> {
let state = Self::make_p1_ctx();
let mut store = wasmtime::Store::new(&self.inner.engine, state);
let instance = wasmtime::Instance::new(&mut store, &self.inner.module, &[])?;
Ok(WasmInstance { store, instance })
}
pub fn wasi_instance(&self) -> Result<WasmInstance, wasmtime::Error> {
let state = Self::make_p1_ctx();
let mut store = wasmtime::Store::new(&self.inner.engine, state);
let mut linker = wasmtime::Linker::new(&self.inner.engine);
wasmtime_wasi::p1::add_to_linker_sync(&mut linker, |s| s)?;
let instance = linker.instantiate(&mut store, &self.inner.module)?;
Ok(WasmInstance { store, instance })
}
pub fn engine(&self) -> &wasmtime::Engine {
&self.inner.engine
}
pub fn module(&self) -> &wasmtime::Module {
&self.inner.module
}
}
impl WasmInstance {
pub fn call<P, R>(&mut self, name: &str, params: P) -> Result<R, wasmtime::Error>
where
P: wasmtime::WasmParams,
R: wasmtime::WasmResults,
{
let func = self
.instance
.get_typed_func::<P, R>(&mut self.store, name)?;
func.call(&mut self.store, params)
}
pub fn typed_func<P, R>(
&mut self,
name: &str,
) -> Result<wasmtime::TypedFunc<P, R>, wasmtime::Error>
where
P: wasmtime::WasmParams,
R: wasmtime::WasmResults,
{
self.instance.get_typed_func::<P, R>(&mut self.store, name)
}
pub fn raw_instance(&self) -> &wasmtime::Instance {
&self.instance
}
}