1#![feature(tuple_trait)]
7#![warn(missing_docs)]
8#![deny(unsafe_code)]
9
10#[doc(no_inline)]
11pub use anyhow::{anyhow, Result};
12
13use serde::{de::DeserializeOwned, Serialize};
14use std::{collections::HashMap, marker::Tuple};
15
16pub const ABI_ALLOC_NAME: &str = "__abi_alloc";
18pub const ABI_FREE_NAME: &str = "__abi_free";
20pub const MEMORY_NAME: &str = "memory";
22
23pub trait RawModule: Sized {
25 type Linker: Linker<Self>;
27
28 type LinkerHandle<'a>: LinkerHandle<'a, Self>;
30
31 type Func;
33
34 fn call<T>(&self, name: &str, args: &[u8], f: impl FnOnce(&[u8]) -> Result<T>) -> Result<T>;
38}
39
40pub struct PluginModule<M: RawModule> {
42 module: M,
43}
44
45impl<M: RawModule> PluginModule<M> {
46 pub fn new(module: M) -> Self {
48 Self { module }
49 }
50
51 pub fn call<P: Serialize, R: DeserializeOwned>(&self, name: &str, args: P) -> Result<R> {
55 let data = rmp_serde::to_vec(&args)?;
56 self.module.call(name, &data, |res| {
57 let res = rmp_serde::from_slice(res)?;
58 Ok(res)
59 })
60 }
61
62 pub fn inner(&self) -> &M {
64 &self.module
65 }
66}
67
68pub trait Linker<M: RawModule>: Sized {
70 type Config;
72
73 fn new(config: Self::Config) -> Result<Self>;
75
76 fn create(&self, binary: &[u8]) -> Result<M>;
78
79 fn import(&mut self, ns: impl Into<String>, funcs: HashMap<String, M::Func>) -> Result<()>;
81
82 fn wrap_raw(
84 &self,
85 f: impl (Fn(M::LinkerHandle<'_>, i32, i32) -> Result<Vec<u8>>) + Send + Sync + 'static,
86 ) -> M::Func;
87
88 fn wrap<P: DeserializeOwned + Tuple, R: Serialize>(
90 &self,
91 f: impl (Fn(P) -> Result<R>) + Send + Sync + 'static,
92 ) -> M::Func {
93 self.wrap_raw(move |handle, start, len| {
94 let data = handle.slice(start, len, |data| rmp_serde::from_slice(data))?;
95 let data = f(data)?;
96 let data = rmp_serde::to_vec(&data)?;
97 Ok(data)
98 })
99 }
100
101 fn wrap_with<P: DeserializeOwned + Tuple, R: Serialize>(
103 &self,
104 f: impl (Fn(M::LinkerHandle<'_>, P) -> Result<R>) + Send + Sync + 'static,
105 ) -> M::Func {
106 self.wrap_raw(move |handle, start, len| {
107 let data = handle.slice(start, len, |data| rmp_serde::from_slice(data))?;
108 let data = f(handle, data)?;
109 let data = rmp_serde::to_vec(&data)?;
110 Ok(data)
111 })
112 }
113}
114
115pub trait LinkerHandle<'a, M: RawModule> {
120 fn call<T>(
122 &mut self,
123 m: &M,
124 name: &str,
125 args: &[u8],
126 f: impl FnOnce(&[u8]) -> Result<T>,
127 ) -> Result<T>;
128
129 fn slice<T>(&self, start: i32, len: i32, f: impl FnOnce(&[u8]) -> T) -> T;
131
132 fn slice_mut<T>(&mut self, start: i32, len: i32, f: impl FnOnce(&mut [u8]) -> T) -> T;
134}