Cargo.lock 🔗
@@ -3717,6 +3717,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
+ "pollster",
"serde",
"serde_json",
"wasi-common",
Isaac Clayton created
Cargo.lock | 1
crates/plugin_runtime/Cargo.toml | 1
crates/plugin_runtime/build.rs | 47 ++++++++++++++++++++++++
crates/plugin_runtime/src/lib.rs | 64 ++++++++++++++++++++++++++++-----
plugins/Cargo.lock | 7 +++
plugins/Cargo.toml | 2
plugins/test_plugin/Cargo.toml | 10 +++++
plugins/test_plugin/src/lib.rs | 44 +++++++++++++++++++++++
8 files changed, 164 insertions(+), 12 deletions(-)
@@ -3717,6 +3717,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
+ "pollster",
"serde",
"serde_json",
"wasi-common",
@@ -11,3 +11,4 @@ anyhow = { version = "1.0", features = ["std"] }
serde = "1.0"
serde_json = "1.0"
bincode = "1.3"
+pollster = "0.2.5"
@@ -0,0 +1,47 @@
+use std::path::Path;
+
+fn main() {
+ let base = Path::new("../../plugins");
+
+ // println!("cargo:rerun-if-changed=../../plugins/*");
+ println!("cargo:warning=Rebuilding plugins...");
+
+ let _ = std::fs::remove_dir_all(base.join("bin"));
+ let _ =
+ std::fs::create_dir_all(base.join("bin")).expect("Could not make plugins bin directory");
+
+ std::process::Command::new("cargo")
+ .args([
+ "build",
+ "--release",
+ "--target",
+ "wasm32-wasi",
+ "--manifest-path",
+ base.join("Cargo.toml").to_str().unwrap(),
+ ])
+ .status()
+ .expect("Could not build plugins");
+
+ let binaries = std::fs::read_dir(base.join("target/wasm32-wasi/release"))
+ .expect("Could not find compiled plugins in target");
+ println!("cargo:warning={:?}", binaries);
+
+ for file in binaries {
+ let is_wasm = || {
+ let path = file.ok()?.path();
+ if path.extension()? == "wasm" {
+ Some(path)
+ } else {
+ None
+ }
+ };
+
+ if let Some(path) = is_wasm() {
+ std::fs::copy(&path, base.join("bin").join(path.file_name().unwrap()))
+ .expect("Could not copy compiled plugin to bin");
+ }
+ }
+
+ // TODO: create .wat versions
+ // TODO: optimize with wasm-opt
+}
@@ -1,14 +1,56 @@
pub mod wasi;
+use pollster::FutureExt as _;
pub use wasi::*;
-// #[cfg(test)]
-// mod tests {
-// use super::*;
-
-// pub fn init_wasi() {
-// let plugin = WasiPluginBuilder::new().init(todo!()).unwrap();
-// let handle: WasiFn<u32, String> = plugin.function("hello").unwrap();
-// let result = plugin.call(handle, 27).unwrap();
-// assert_eq!(result, "world 27");
-// }
-// }
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ pub fn test_plugin() {
+ pub struct TestPlugin {
+ noop: WasiFn<(), ()>,
+ constant: WasiFn<(), u32>,
+ identity: WasiFn<u32, u32>,
+ add: WasiFn<(u32, u32), u32>,
+ swap: WasiFn<(u32, u32), (u32, u32)>,
+ sort: WasiFn<Vec<u32>, Vec<u32>>,
+ print: WasiFn<String, ()>,
+ // and_back: WasiFn<u32, u32>,
+ }
+
+ async {
+ let mut runtime = WasiPluginBuilder::new_with_default_ctx()
+ .unwrap()
+ .host_function("mystery_number", |input: u32| input + 7)
+ .unwrap()
+ .init(include_bytes!("../../../plugins/bin/test_plugin.wasm"))
+ .await
+ .unwrap();
+
+ let plugin = TestPlugin {
+ noop: runtime.function("noop").unwrap(),
+ constant: runtime.function("constant").unwrap(),
+ identity: runtime.function("identity").unwrap(),
+ add: runtime.function("add").unwrap(),
+ swap: runtime.function("swap").unwrap(),
+ sort: runtime.function("sort").unwrap(),
+ print: runtime.function("print").unwrap(),
+ // and_back: runtime.function("and_back").unwrap(),
+ };
+
+ let unsorted = vec![1, 3, 4, 2, 5];
+ let sorted = vec![1, 2, 3, 4, 5];
+
+ assert_eq!(runtime.call(&plugin.noop, ()).await.unwrap(), ());
+ assert_eq!(runtime.call(&plugin.constant, ()).await.unwrap(), 27);
+ assert_eq!(runtime.call(&plugin.identity, 58).await.unwrap(), 58);
+ assert_eq!(runtime.call(&plugin.add, (3, 4)).await.unwrap(), 7);
+ assert_eq!(runtime.call(&plugin.swap, (1, 2)).await.unwrap(), (2, 1));
+ assert_eq!(runtime.call(&plugin.sort, unsorted).await.unwrap(), sorted);
+ assert_eq!(runtime.call(&plugin.print, "Hi!".into()).await.unwrap(), ());
+ // assert_eq!(runtime.call(&plugin.and_back, 1).await.unwrap(), 8);
+ }
+ .block_on()
+ }
+}
@@ -112,6 +112,13 @@ dependencies = [
"unicode-ident",
]
+[[package]]
+name = "test_plugin"
+version = "0.1.0"
+dependencies = [
+ "plugin",
+]
+
[[package]]
name = "unicode-ident"
version = "1.0.0"
@@ -1,2 +1,2 @@
[workspace]
-members = ["./json_language"]
+members = ["./json_language", "./test_plugin"]
@@ -0,0 +1,10 @@
+[package]
+name = "test_plugin"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+plugin = { path = "../../crates/plugin" }
+
+[lib]
+crate-type = ["cdylib"]
@@ -0,0 +1,44 @@
+use plugin::prelude::*;
+
+#[export]
+pub fn noop() {}
+
+#[export]
+pub fn constant() -> u32 {
+ 27
+}
+
+#[export]
+pub fn identity(i: u32) -> u32 {
+ i
+}
+
+#[export]
+pub fn add(a: u32, b: u32) -> u32 {
+ a + b
+}
+
+#[export]
+pub fn swap(a: u32, b: u32) -> (u32, u32) {
+ (b, a)
+}
+
+#[export]
+pub fn sort(mut list: Vec<u32>) -> Vec<u32> {
+ list.sort();
+ list
+}
+
+#[export]
+pub fn print(string: String) {
+ println!("to stdout: {}", string);
+ eprintln!("to stderr: {}", string);
+}
+
+// #[import]
+// fn mystery_number(input: u32) -> u32;
+
+// #[export]
+// pub fn and_back(secret: u32) -> u32 {
+// mystery_number(secret)
+// }