1# Zed's Plugin Runner
2Wasm plugins can be run through `wasmtime`, with supported for sandboxed system integration through WASI. There are three `plugin` crates that implement different things:
3
41. `plugin_runtime` loads and runs compiled `Wasm` plugins, and handles setting up system bindings.
5
62. `plugin` is the crate that Rust Wasm plugins should depend on. It re-exports some required crates (e.g. `serde`, `bincode`) and provides some necessary macros for generating bindings that `plugin_runtime` can hook into.
7
83. `plugin_macros` implements the proc macros required by `plugin`, like the `#[bind]` attribute macro.
9
10## ABI
11The interface between the host Rust runtime ('Runtime') and plugins implemented in Wasm ('Plugin') is pretty simple.
12
13`Buffer` is a pair of two 4-byte (`u32`) fields, encoded as a single `u64`.
14
15```
16struct Buffer {
17 ptr: u32,
18 len: u32,
19}
20```
21
22All functions that Plugin exports must have the following properties:
23
24- Have the signature `fn(ptr: u64) -> u64`, where both the argument and return types are a `Buffer`:
25
26 - The input `Buffer` will contain the input arguments serialized to `bincode`.
27 - The output `Buffer` will contain the output arguments serialized to `bincode`.
28
29- Have a name starting with two underscores.
30
31Additionally, Plugin must export an:
32
33- `__alloc_buffer` function that, given a `u32` length, returns a `u32` pointer to a buffer of that length.
34- `__free_buffer` function that, given a buffer encoded as a `u64`, frees the buffer at the given location, and does not return anything.
35
36Note that all of these requirements are automatically fullfilled for any Rust Wasm plugin that uses the `plugin` crate, and imports the `prelude`.
37
38Here's an example Rust Wasm plugin that doubles the value of every float in a `Vec<f64>` passed into it:
39
40```rust
41use plugin::prelude::*;
42
43#[export]
44pub fn double(mut x: Vec<f64>) -> Vec<f64> {
45 x.into_iter().map(|x| x * 2.0).collect()
46}
47```
48
49All the serialization code is automatically generated by `#[export]`.
50
51You can specify functions that must be defined host-side by using the `#[import]` attribute. This attribute must be attached to a function signature:
52
53```rust
54#[import]
55fn run(command: String) -> Vec<u8>;
56```
57
58The `#[import]` macro will generate a function body that performs the proper serialization/deserialization needed to call out to the host rust runtime. Note that the same ABI is used for both `#[import]` and `#[export]`.