#![feature(tuple_trait)]
#![warn(missing_docs)]
#![deny(unsafe_code)]
#[doc(no_inline)]
pub use anyhow::{anyhow, Result};
use serde::{de::DeserializeOwned, Serialize};
use std::{collections::HashMap, marker::Tuple};
pub const ABI_ALLOC_NAME: &str = "__abi_alloc";
pub const ABI_FREE_NAME: &str = "__abi_free";
pub const MEMORY_NAME: &str = "memory";
pub trait RawModule: Sized {
type Linker: Linker<Self>;
type LinkerHandle<'a>: LinkerHandle<'a, Self>;
type Func;
fn call<T>(&self, name: &str, args: &[u8], f: impl FnOnce(&[u8]) -> Result<T>) -> Result<T>;
}
pub struct PluginModule<M: RawModule> {
module: M,
}
impl<M: RawModule> PluginModule<M> {
pub fn new(module: M) -> Self {
Self { module }
}
pub fn call<P: Serialize, R: DeserializeOwned>(&self, name: &str, args: P) -> Result<R> {
let data = rmp_serde::to_vec(&args)?;
self.module.call(name, &data, |res| {
let res = rmp_serde::from_slice(res)?;
Ok(res)
})
}
pub fn inner(&self) -> &M {
&self.module
}
}
pub trait Linker<M: RawModule>: Sized {
type Config;
fn new(config: Self::Config) -> Result<Self>;
fn create(&self, binary: &[u8]) -> Result<M>;
fn import(&mut self, ns: impl Into<String>, funcs: HashMap<String, M::Func>) -> Result<()>;
fn wrap_raw(
&self,
f: impl (Fn(M::LinkerHandle<'_>, i32, i32) -> Result<Vec<u8>>) + Send + Sync + 'static,
) -> M::Func;
fn wrap<P: DeserializeOwned + Tuple, R: Serialize>(
&self,
f: impl (Fn(P) -> Result<R>) + Send + Sync + 'static,
) -> M::Func {
self.wrap_raw(move |handle, start, len| {
let data = handle.slice(start, len, |data| rmp_serde::from_slice(data))?;
let data = f(data)?;
let data = rmp_serde::to_vec(&data)?;
Ok(data)
})
}
fn wrap_with<P: DeserializeOwned + Tuple, R: Serialize>(
&self,
f: impl (Fn(M::LinkerHandle<'_>, P) -> Result<R>) + Send + Sync + 'static,
) -> M::Func {
self.wrap_raw(move |handle, start, len| {
let data = handle.slice(start, len, |data| rmp_serde::from_slice(data))?;
let data = f(handle, data)?;
let data = rmp_serde::to_vec(&data)?;
Ok(data)
})
}
}
pub trait LinkerHandle<'a, M: RawModule> {
fn call<T>(
&mut self,
m: &M,
name: &str,
args: &[u8],
f: impl FnOnce(&[u8]) -> Result<T>,
) -> Result<T>;
fn slice<T>(&self, start: i32, len: i32, f: impl FnOnce(&[u8]) -> T) -> T;
fn slice_mut<T>(&mut self, start: i32, len: i32, f: impl FnOnce(&mut [u8]) -> T) -> T;
}