use crate::{types::Val, GlobalType, WasmEdgeResult};
use wasmedge_sys as sys;
#[derive(Debug, Clone)]
pub struct Global {
pub(crate) inner: sys::Global,
pub(crate) name: Option<String>,
pub(crate) mod_name: Option<String>,
pub(crate) ty: GlobalType,
}
impl Global {
pub fn new(ty: GlobalType, init: Val) -> WasmEdgeResult<Self> {
let inner = sys::Global::create(&ty.clone().into(), init.into())?;
Ok(Self {
inner,
name: None,
mod_name: None,
ty,
})
}
pub fn name(&self) -> Option<&str> {
match &self.name {
Some(name) => Some(name.as_ref()),
None => None,
}
}
pub fn mod_name(&self) -> Option<&str> {
match &self.mod_name {
Some(mod_name) => Some(mod_name.as_ref()),
None => None,
}
}
pub fn ty(&self) -> &GlobalType {
&self.ty
}
pub fn get_value(&self) -> Val {
self.inner.get_value().into()
}
pub fn set_value(&mut self, val: Val) -> WasmEdgeResult<()> {
self.inner.set_value(val.into())?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
config::{CommonConfigOptions, ConfigBuilder},
error::{GlobalError, WasmEdgeError},
Executor, ImportObjectBuilder, Mutability, NeverType, Statistics, Store, ValType,
};
#[test]
fn test_global_type() {
let global_ty = GlobalType::new(ValType::I32, Mutability::Const);
assert_eq!(global_ty.value_ty(), ValType::I32);
assert_eq!(global_ty.mutability(), Mutability::Const);
}
#[test]
#[allow(clippy::assertions_on_result_states)]
fn test_global_basic() {
let result = Global::new(
GlobalType::new(ValType::I32, Mutability::Const),
Val::I32(1314),
);
assert!(result.is_ok());
let global_const = result.unwrap();
let result = Global::new(
GlobalType::new(ValType::F32, Mutability::Var),
Val::F32(13.14),
);
assert!(result.is_ok());
let global_var = result.unwrap();
let result = ImportObjectBuilder::new()
.with_global("const-global", global_const)
.with_global("var-global", global_var)
.build::<NeverType>("extern", 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());
let result = store.named_instance("extern");
assert!(result.is_ok());
let instance = result.unwrap();
let result = instance.global("const-global");
assert!(result.is_ok());
let mut const_global = result.unwrap();
assert!(const_global.name().is_some());
assert_eq!(const_global.name().unwrap(), "const-global");
assert!(const_global.mod_name().is_some());
assert_eq!(const_global.mod_name().unwrap(), "extern");
let ty = const_global.ty();
assert_eq!(ty.value_ty(), ValType::I32);
assert_eq!(ty.mutability(), Mutability::Const);
if let Val::I32(value) = const_global.get_value() {
assert_eq!(value, 1314);
}
let result = const_global.set_value(Val::I32(314));
assert!(result.is_err());
assert_eq!(
result.unwrap_err(),
Box::new(WasmEdgeError::Global(GlobalError::ModifyConst))
);
let result = store.named_instance("extern");
assert!(result.is_ok());
let instance = result.unwrap();
let result = instance.global("var-global");
assert!(result.is_ok());
let mut var_global = result.unwrap();
assert!(var_global.name().is_some());
assert_eq!(var_global.name().unwrap(), "var-global");
assert!(var_global.mod_name().is_some());
assert_eq!(var_global.mod_name().unwrap(), "extern");
let ty = var_global.ty();
assert_eq!(ty.value_ty(), ValType::F32);
assert_eq!(ty.mutability(), Mutability::Var);
if let Val::F32(value) = var_global.get_value() {
assert_eq!(value, 13.14);
}
let result = var_global.set_value(Val::F32(1.314));
assert!(result.is_ok());
let result = instance.global("var-global");
assert!(result.is_ok());
let var_global = result.unwrap();
if let Val::F32(value) = var_global.get_value() {
assert_eq!(value, 1.314);
}
}
}