forked from feather-rs/feather
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwasm.rs
More file actions
77 lines (65 loc) · 2.11 KB
/
wasm.rs
File metadata and controls
77 lines (65 loc) · 2.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::sync::Arc;
use quill_plugin_format::PluginMetadata;
use wasmer::{
ChainableNamedResolver, Features, Function, ImportObject, Instance, Module, NativeFunc, Store,
};
use wasmer_wasi::{WasiEnv, WasiState, WasiVersion};
use crate::{
context::{PluginContext, PluginPtr, PluginPtrMut},
env::PluginEnv,
PluginManager,
};
pub struct WasmPlugin {
/// The WebAssembly instancing containing
/// the plugin.
instance: Instance,
/// Exported function to enable the plugin.
enable: Function,
/// Exported function to run a system given its data pointer.
run_system: NativeFunc<u32>,
}
impl WasmPlugin {
pub fn load(
manager: &PluginManager,
cx: &Arc<PluginContext>,
module: &[u8],
metadata: &PluginMetadata,
) -> anyhow::Result<Self> {
let env = PluginEnv {
context: Arc::clone(cx),
};
let quill_imports = crate::host_calls::generate_import_object(&manager.store, &env);
let wasi_imports = generate_wasi_import_object(&manager.store, &metadata.identifier)?;
let imports = quill_imports.chain_back(wasi_imports);
let module = Module::new(&manager.store, module)?;
let instance = Instance::new(&module, &imports)?;
let run_system = instance
.exports
.get_function("quill_run_system")?
.native()?
.clone();
let enable = instance.exports.get_function("quill_setup")?.clone();
Ok(Self {
instance,
run_system,
enable,
})
}
pub fn enable(&self) -> anyhow::Result<()> {
self.enable.call(&[])?;
Ok(())
}
pub fn run_system(&self, data_ptr: PluginPtrMut<u8>) -> anyhow::Result<()> {
self.run_system.call(data_ptr.ptr as u32)?;
Ok(())
}
}
fn generate_wasi_import_object(store: &Store, plugin_name: &str) -> anyhow::Result<ImportObject> {
let state = WasiState::new(plugin_name).build()?;
let env = WasiEnv::new(state);
Ok(wasmer_wasi::generate_import_object_from_env(
store,
env,
WasiVersion::Latest,
))
}