ayaka_plugin/
lib.rs

1//! Base crate for plugin runtimes.
2//!
3//! This crate provides abstract types and traits
4//! for different plugin backends.
5
6#![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
16/// The exported method `__abi_alloc`.
17pub const ABI_ALLOC_NAME: &str = "__abi_alloc";
18/// The exported method `__abi_free`.
19pub const ABI_FREE_NAME: &str = "__abi_free";
20/// The default exported memory name.
21pub const MEMORY_NAME: &str = "memory";
22
23/// Represents a raw plugin module.
24pub trait RawModule: Sized {
25    /// The linker type that can create raw module.
26    type Linker: Linker<Self>;
27
28    /// The linker handle type.
29    type LinkerHandle<'a>: LinkerHandle<'a, Self>;
30
31    /// The import function type.
32    type Func;
33
34    /// Calls a method by name.
35    ///
36    /// The args and returns are bytes.
37    fn call<T>(&self, name: &str, args: &[u8], f: impl FnOnce(&[u8]) -> Result<T>) -> Result<T>;
38}
39
40/// High-level wrapper for plugin module.
41pub struct PluginModule<M: RawModule> {
42    module: M,
43}
44
45impl<M: RawModule> PluginModule<M> {
46    /// Creates a wrapper on raw module.
47    pub fn new(module: M) -> Self {
48        Self { module }
49    }
50
51    /// Call a method by name.
52    ///
53    /// The args and returns are passed by MessagePack with [`rmp_serde`].
54    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    /// Get inner raw module.
63    pub fn inner(&self) -> &M {
64        &self.module
65    }
66}
67
68/// Represents the linker of plugin modules.
69pub trait Linker<M: RawModule>: Sized {
70    /// Config type to create the linker.
71    type Config;
72
73    /// Create the linker.
74    fn new(config: Self::Config) -> Result<Self>;
75
76    /// Create a raw module from binary.
77    fn create(&self, binary: &[u8]) -> Result<M>;
78
79    /// Import functions by namespace and names.
80    fn import(&mut self, ns: impl Into<String>, funcs: HashMap<String, M::Func>) -> Result<()>;
81
82    /// Wrap a function with args in bytes.
83    fn wrap_raw(
84        &self,
85        f: impl (Fn(M::LinkerHandle<'_>, i32, i32) -> Result<Vec<u8>>) + Send + Sync + 'static,
86    ) -> M::Func;
87
88    /// Wrap a function with args.
89    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    /// Wrap a function with args and linker handle.
102    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
115/// Represents a handle of linker.
116///
117/// Usually it is not easy to call function inside host functions.
118/// A handle provides methods to do so.
119pub trait LinkerHandle<'a, M: RawModule> {
120    /// Call methods of a module.
121    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    /// Get memory slice.
130    fn slice<T>(&self, start: i32, len: i32, f: impl FnOnce(&[u8]) -> T) -> T;
131
132    /// Get memory mutable slice.
133    fn slice_mut<T>(&mut self, start: i32, len: i32, f: impl FnOnce(&mut [u8]) -> T) -> T;
134}