use crate::{plugin::PluginInstance, Executor, ImportObject, Instance, Module, WasmEdgeResult};
use wasmedge_sys as sys;
#[derive(Debug, Clone)]
pub struct Store {
pub(crate) inner: sys::Store,
}
impl Store {
pub fn new() -> WasmEdgeResult<Self> {
let inner = sys::Store::create()?;
Ok(Self { inner })
}
pub fn register_import_module<T>(
&mut self,
executor: &mut Executor,
import: &ImportObject<T>,
) -> WasmEdgeResult<()>
where
T: ?Sized + Send + Sync + Clone,
{
executor
.inner
.register_import_module(&self.inner, &import.0)
}
pub fn register_named_module(
&mut self,
executor: &mut Executor,
mod_name: impl AsRef<str>,
module: &Module,
) -> WasmEdgeResult<Instance> {
let inner_instance =
executor
.inner
.register_named_module(&self.inner, &module.inner, mod_name.as_ref())?;
Ok(Instance {
inner: inner_instance,
})
}
pub fn register_active_module(
&mut self,
executor: &mut Executor,
module: &Module,
) -> WasmEdgeResult<Instance> {
let inner = executor
.inner
.register_active_module(&self.inner, &module.inner)?;
Ok(Instance { inner })
}
pub fn register_plugin_module(
&mut self,
executor: &mut Executor,
plugin: &PluginInstance,
) -> WasmEdgeResult<()> {
executor
.inner
.register_plugin_instance(&self.inner, &plugin.inner)
}
pub fn named_instance_count(&self) -> u32 {
self.inner.module_len()
}
pub fn instance_names(&self) -> Vec<String> {
match self.inner.module_names() {
Some(names) => names,
None => vec![],
}
}
pub fn named_instance(&mut self, name: impl AsRef<str>) -> WasmEdgeResult<Instance> {
let inner_instance = self.inner.module(name.as_ref())?;
Ok(Instance {
inner: inner_instance,
})
}
pub fn contains(&self, mod_name: impl AsRef<str>) -> bool {
self.inner.contains(mod_name.as_ref())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
config::{CommonConfigOptions, ConfigBuilder},
error::HostFuncError,
types::Val,
CallingFrame, Executor, Global, GlobalType, ImportObjectBuilder, Memory, MemoryType,
Module, Mutability, NeverType, RefType, Statistics, Table, TableType, ValType, WasmValue,
};
#[test]
#[allow(clippy::assertions_on_result_states)]
fn test_store_create() {
let result = ConfigBuilder::new(CommonConfigOptions::default()).build();
assert!(result.is_ok());
let config = result.unwrap();
let result = Statistics::new();
assert!(result.is_ok());
let mut stat = result.unwrap();
let result = Executor::new(Some(&config), Some(&mut stat));
assert!(result.is_ok());
let result = Store::new();
assert!(result.is_ok());
let store = result.unwrap();
assert_eq!(store.named_instance_count(), 0);
}
#[test]
#[allow(clippy::assertions_on_result_states)]
fn test_store_register_import_module() {
let result = Global::new(
GlobalType::new(ValType::F32, Mutability::Const),
Val::F32(3.5),
);
assert!(result.is_ok());
let global_const = result.unwrap();
let result = MemoryType::new(10, None, false);
assert!(result.is_ok());
let memory_type = result.unwrap();
let result = Memory::new(memory_type);
assert!(result.is_ok());
let memory = result.unwrap();
let result = Table::new(TableType::new(RefType::FuncRef, 5, None));
assert!(result.is_ok());
let table = result.unwrap();
let result = ImportObjectBuilder::new()
.with_func::<(i32, i32), i32, NeverType>("add", real_add, None)
.expect("failed to add host function")
.with_global("global", global_const)
.with_memory("mem", memory)
.with_table("table", table)
.build::<NeverType>("extern-module", None);
assert!(result.is_ok());
let import = result.unwrap();
let result = ConfigBuilder::new(CommonConfigOptions::default()).build();
assert!(result.is_ok());
let config = result.unwrap();
let result = Statistics::new();
assert!(result.is_ok());
let mut stat = result.unwrap();
let result = Executor::new(Some(&config), Some(&mut stat));
assert!(result.is_ok());
let mut executor = result.unwrap();
let result = Store::new();
assert!(result.is_ok());
let mut store = result.unwrap();
let result = store.register_import_module(&mut executor, &import);
assert!(result.is_ok());
assert_eq!(store.named_instance_count(), 1);
assert_eq!(store.instance_names(), ["extern-module"]);
let result = store.named_instance("extern-module");
assert!(result.is_ok());
let instance = result.unwrap();
assert!(instance.name().is_some());
assert_eq!(instance.name().unwrap(), "extern-module");
let result = instance.global("global");
assert!(result.is_ok());
let global = result.unwrap();
let ty = global.ty();
assert_eq!(*ty, GlobalType::new(ValType::F32, Mutability::Const));
}
#[test]
#[allow(clippy::assertions_on_result_states)]
fn test_store_register_named_module() {
let result = ConfigBuilder::new(CommonConfigOptions::default()).build();
assert!(result.is_ok());
let config = result.unwrap();
let result = Statistics::new();
assert!(result.is_ok());
let mut stat = result.unwrap();
let result = Executor::new(Some(&config), Some(&mut stat));
assert!(result.is_ok());
let mut executor = result.unwrap();
let result = Store::new();
assert!(result.is_ok());
let mut store = result.unwrap();
let file = std::env::current_dir()
.unwrap()
.join("examples/wasmedge-sys/data/fibonacci.wat");
let result = Module::from_file(Some(&config), file);
assert!(result.is_ok());
let module = result.unwrap();
let result = store.register_named_module(&mut executor, "extern-module", &module);
assert!(result.is_ok());
assert_eq!(store.named_instance_count(), 1);
assert_eq!(store.instance_names(), ["extern-module"]);
let result = store.named_instance("extern-module");
assert!(result.is_ok());
let instance = result.unwrap();
assert!(instance.name().is_some());
assert_eq!(instance.name().unwrap(), "extern-module");
}
#[test]
fn test_store_register_active_module() {
let result = ConfigBuilder::new(CommonConfigOptions::default()).build();
assert!(result.is_ok());
let config = result.unwrap();
let result = Statistics::new();
assert!(result.is_ok());
let mut stat = result.unwrap();
let result = Executor::new(Some(&config), Some(&mut stat));
assert!(result.is_ok());
let mut executor = result.unwrap();
let result = Store::new();
assert!(result.is_ok());
let mut store = result.unwrap();
let file = std::env::current_dir()
.unwrap()
.join("examples/wasmedge-sys/data/fibonacci.wat");
let result = Module::from_file(Some(&config), file);
assert!(result.is_ok());
let module = result.unwrap();
let result = store.register_active_module(&mut executor, &module);
assert!(result.is_ok());
let active_instance = result.unwrap();
assert!(active_instance.name().is_none());
let result = active_instance.func("fib");
assert!(result.is_ok());
assert_eq!(store.named_instance_count(), 0);
assert_eq!(store.instance_names().len(), 0);
}
#[test]
#[allow(clippy::assertions_on_result_states)]
fn test_store_basic() {
let result = ConfigBuilder::new(CommonConfigOptions::default()).build();
assert!(result.is_ok());
let config = result.unwrap();
let result = Statistics::new();
assert!(result.is_ok());
let mut stat = result.unwrap();
let result = Executor::new(Some(&config), Some(&mut stat));
assert!(result.is_ok());
let mut executor = result.unwrap();
let result = Store::new();
assert!(result.is_ok());
let mut store = result.unwrap();
let result = Global::new(
GlobalType::new(ValType::F32, Mutability::Const),
Val::F32(3.5),
);
assert!(result.is_ok());
let global_const = result.unwrap();
let result = MemoryType::new(10, None, false);
assert!(result.is_ok());
let memory_type = result.unwrap();
let result = Memory::new(memory_type);
assert!(result.is_ok());
let memory = result.unwrap();
let result = Table::new(TableType::new(RefType::FuncRef, 5, None));
assert!(result.is_ok());
let table = result.unwrap();
let result = ImportObjectBuilder::new()
.with_func::<(i32, i32), i32, NeverType>("add", real_add, None)
.expect("failed to add host function")
.with_global("global", global_const)
.with_memory("mem", memory)
.with_table("table", table)
.build::<NeverType>("extern-module", None);
assert!(result.is_ok());
let import = result.unwrap();
let result = store.register_import_module(&mut executor, &import);
assert!(result.is_ok());
let file = std::env::current_dir()
.unwrap()
.join("examples/wasmedge-sys/data/fibonacci.wat");
let result = Module::from_file(Some(&config), file);
assert!(result.is_ok());
let module = result.unwrap();
let result = store.register_named_module(&mut executor, "fib-module", &module);
assert!(result.is_ok());
assert_eq!(store.named_instance_count(), 2);
let mod_names = store.instance_names();
assert_eq!(mod_names[0], "extern-module");
assert_eq!(mod_names[1], "fib-module");
assert_eq!(mod_names[0], "extern-module");
let result = store.named_instance(&mod_names[0]);
assert!(result.is_ok());
let instance = result.unwrap();
assert!(instance.name().is_some());
assert_eq!(instance.name().unwrap(), mod_names[0]);
assert_eq!(mod_names[1], "fib-module");
let result = store.named_instance(&mod_names[1]);
assert!(result.is_ok());
let instance = result.unwrap();
assert!(instance.name().is_some());
assert_eq!(instance.name().unwrap(), mod_names[1]);
}
fn real_add(
_frame: CallingFrame,
inputs: Vec<WasmValue>,
_data: *mut std::os::raw::c_void,
) -> std::result::Result<Vec<WasmValue>, HostFuncError> {
if inputs.len() != 2 {
return Err(HostFuncError::User(1));
}
let a = if inputs[0].ty() == ValType::I32 {
inputs[0].to_i32()
} else {
return Err(HostFuncError::User(2));
};
let b = if inputs[1].ty() == ValType::I32 {
inputs[1].to_i32()
} else {
return Err(HostFuncError::User(3));
};
let c = a + b;
Ok(vec![WasmValue::from_i32(c)])
}
}