Skip to content

Commit

Permalink
Update wasmer and switch to wasmer-wasix
Browse files Browse the repository at this point in the history
  • Loading branch information
jareddlc committed Sep 3, 2024
1 parent 7e2cd9d commit fac3db6
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 46 deletions.
11 changes: 6 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
[package]
name = "gut"
version = "0.2.2"
version = "0.3.0"
authors = ["Jared De La Cruz <[email protected]>"]
edition = "2018"

[dependencies]
libloading = "0.7"
libloading = "0.8.5"
serde_json = "1"
gut-lib = "0.1"
reqwest = { version = "0.11", features = ["blocking"] }
wasmer = "2"
wasmer-wasi = "2"
reqwest = { version = "0.12", features = ["blocking"] }
tokio = "1"
wasmer = "4"
wasmer-wasix = "0.26"

[profile.release]
codegen-units = 1
Expand Down
132 changes: 91 additions & 41 deletions src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ use libloading::{Library, Symbol};
use std::ffi::CString;
use std::fs;
use std::os::raw::c_char;
use wasmer::{Array, Instance, Memory, Module, NativeFunc, Store, Value, WasmPtr};
use wasmer_wasi::WasiState;
use wasmer::{Instance, Memory, Module, Store, TypedFunction, Value, WasmPtr};
use wasmer_wasix::{WasiEnv, WasiFunctionEnv};

use crate::gut_lib;

pub struct WasmPlugin {
instance: Instance,
store: Store,
wasi_env: WasiFunctionEnv,
}

#[derive(Clone, Debug, Default)]
pub struct Plugin {
descriptions: Vec<String>,
Expand Down Expand Up @@ -100,32 +106,47 @@ impl Plugins {
if plugin.functions.contains(&name) {
// load wasm
if plugin.path.contains(".wasm") {
// create instance of wasm plugin
let instance = Self::load_wasm(&plugin.path);
// create wasm plugin
let wasi_plugin = Self::load_wasm(&plugin.path);

// get instance, store, and wasi env
let instance = wasi_plugin.instance;
let mut store = wasi_plugin.store;
let mut wasi_env = wasi_plugin.wasi_env;

// create memory of the wasm plugin
let memory: &Memory = instance
.exports
.get_memory("memory")
.expect("Failed to get instance memory");
.expect("Failed to get memory");

// create runtime
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.expect("Failed to create tokio runtime");
let _guard = runtime.enter();

// initailize wasi env
wasi_env
.initialize(&mut store, instance.clone())
.expect("Failed to initialize wasi_env");

// create function definition
let lib_fn = instance
.exports
.get_function(&name)
.expect("Failed to get function");

// write the string into the lineary memory
for (byte, cell) in argument
.bytes()
.zip(memory.view()[0 as usize..(argument.len()) as usize].iter())
{
cell.set(byte);
}
// write the string argument into the lineary memory
let memory_view = memory.view(&store);
memory_view
.write(1, &argument.as_bytes())
.expect("Failed to write to memory");

// invoke function
lib_fn
.call(&[Value::I32(0)])
.call(&mut store, &[Value::I32(argument.as_bytes().len() as i32)])
.expect("Failed to invoke function");
} else {
unsafe {
Expand Down Expand Up @@ -202,44 +223,58 @@ impl Plugins {
pub fn load_wasm_plugin(path: &String) -> Plugin {
let path = path.clone();

// create instance of wasm plugin
let instance = Self::load_wasm(&path);
// create wasm plugin
let wasi_plugin = Self::load_wasm(&path);

// create memory of the wasm plugin
// get instance, store, and wasi env
let instance = wasi_plugin.instance;
let mut store = wasi_plugin.store;
let mut wasi_env = wasi_plugin.wasi_env;

// create memory
let memory: &Memory = instance
.exports
.get_memory("memory")
.expect("Failed to get instance memory");
.expect("Failed to get memory");

// create runtime
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.expect("Failed to create tokio runtime");
let _guard = runtime.enter();

// initailize wasi env
wasi_env
.initialize(&mut store, instance.clone())
.expect("Failed to initialize wasi_env");

// define gut export functions
let functions: NativeFunc<(), WasmPtr<u8, Array>> = instance
let functions: TypedFunction<(), WasmPtr<u8>> = instance
.exports
.get_native_function("gut_export_functions")
.get_typed_function(&mut store, "gut_export_functions")
.expect("Failed to define gut_export_functions");
let descriptions: NativeFunc<(), WasmPtr<u8, Array>> = instance
let descriptions: TypedFunction<(), WasmPtr<u8>> = instance
.exports
.get_native_function("gut_export_descriptions")
.get_typed_function(&mut store, "gut_export_descriptions")
.expect("Failed to define gut_export_descriptions");

// invoke gut export functions
let functions_ptr: WasmPtr<u8, Array> = functions
.call()
let functions_ptr: WasmPtr<u8> = functions
.call(&mut store)
.expect("Failed to call gut_export_functions");
let descriptions_ptr: WasmPtr<u8, Array> = descriptions
.call()
let descriptions_ptr: WasmPtr<u8> = descriptions
.call(&mut store)
.expect("Failed to call gut_export_descriptions");

// get strings from memory
let functions_str = unsafe {
functions_ptr
.get_utf8_str_with_nul(memory)
.expect("Failed to get array from memory")
};
let descriptions_str = unsafe {
descriptions_ptr
.get_utf8_str_with_nul(memory)
.expect("Failed to get array from memory")
};
let memory_view = memory.view(&store);
let functions_str = functions_ptr
.read_utf8_string_with_nul(&memory_view)
.expect("Failed to get string from memory");
let descriptions_str = descriptions_ptr
.read_utf8_string_with_nul(&memory_view)
.expect("Failed to get string from memory");

// parse json strings
let descriptions: Vec<String> =
Expand All @@ -254,24 +289,39 @@ impl Plugins {
}
}

pub fn load_wasm(path: &String) -> Instance {
pub fn load_wasm(path: &String) -> WasmPlugin {
// create default store
let store = Store::default();
let mut store = Store::default();

// create module from plugin path
let module = Module::from_file(&store, &path).expect("Failed to load module");

// create runtime
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.expect("Failed to create tokio runtime");
let _guard = runtime.enter();

// create an environment
let mut wasi_env = WasiState::new("Gut")
.finalize()
let wasi_env = WasiEnv::builder("Gut")
.finalize(&mut store)
.expect("Failed to create wasi env");

// create imports
let import_object = wasi_env
.import_object(&module)
.import_object(&mut store, &module)
.expect("Failed to create import object");

// create instance of wasm plugin
Instance::new(&module, &import_object).expect("Failed to create instance")
let instance =
Instance::new(&mut store, &module, &import_object).expect("Failed to create instance");

// wasi_env.on_exit(&mut store, None);
WasmPlugin {
instance,
store,
wasi_env,
}
}
}

0 comments on commit fac3db6

Please sign in to comment.