use std::sync::Arc;
use anyhow::Result;
use dashmap::DashMap;
use tokio::task::JoinHandle;
use crate::state::ProcessState;
use self::wasmtime::{WasmtimeCompiledModule, WasmtimeRuntime};
pub mod wasmtime;
pub struct RawWasm {
pub id: Option<u64>,
pub bytes: Vec<u8>,
}
impl RawWasm {
pub fn new(id: Option<u64>, bytes: Vec<u8>) -> Self {
Self { id, bytes }
}
pub fn as_slice(&self) -> &[u8] {
self.bytes.as_slice()
}
}
impl From<Vec<u8>> for RawWasm {
fn from(bytes: Vec<u8>) -> Self {
Self::new(None, bytes)
}
}
pub trait WasmRuntime<T>: Clone
where
T: crate::state::ProcessState + Default + Send,
{
type WasmInstance: WasmInstance;
fn compile_module(&mut self, data: RawWasm) -> anyhow::Result<usize>;
fn wasm_module(&self, index: usize) -> Option<&RawWasm>;
}
pub trait WasmInstance {
type Param;
}
pub struct Modules<T> {
modules: Arc<DashMap<u64, Arc<WasmtimeCompiledModule<T>>>>,
}
impl<T> Clone for Modules<T> {
fn clone(&self) -> Self {
Self {
modules: self.modules.clone(),
}
}
}
impl<T> Default for Modules<T> {
fn default() -> Self {
Self {
modules: Arc::new(DashMap::new()),
}
}
}
impl<T: ProcessState + 'static> Modules<T> {
pub fn get(&self, module_id: u64) -> Option<Arc<WasmtimeCompiledModule<T>>> {
self.modules.get(&module_id).map(|m| m.clone())
}
pub fn compile(
&self,
runtime: WasmtimeRuntime,
wasm: RawWasm,
) -> JoinHandle<Result<Arc<WasmtimeCompiledModule<T>>>> {
let modules = self.modules.clone();
tokio::task::spawn_blocking(move || {
let id = wasm.id;
match runtime.compile_module(wasm) {
Ok(m) => {
let module = Arc::new(m);
if let Some(id) = id {
modules.insert(id, Arc::clone(&module));
}
Ok(module)
}
Err(e) => Err(e),
}
})
}
}