use wasm3x_sys as ffi;
use crate::error::{Error, Result};
use crate::store::{AsContext, AsContextMut, StoreId, assert_same_store};
use crate::value::{GlobalType, Mutability, Val, ValType};
#[derive(Debug, Clone, Copy)]
pub struct Global {
raw: ffi::IM3Global,
store_id: StoreId,
}
impl Global {
pub(crate) fn from_raw(raw: ffi::IM3Global, store_id: StoreId) -> Self {
Self { raw, store_id }
}
pub fn ty(&self, store: impl AsContext) -> Result<GlobalType> {
assert_same_store(store.as_context().store_id(), self.store_id);
let content = ValType::from_ffi(unsafe { ffi::m3_GetGlobalType(self.raw) })
.ok_or_else(|| Error::new("global has an unsupported value type"))?;
let mutability = if unsafe { ffi::wasm3x_GetGlobalMutable(self.raw) } {
Mutability::Mutable
} else {
Mutability::Const
};
Ok(GlobalType::new(content, mutability))
}
pub fn get(&self, store: impl AsContext) -> Result<Val> {
assert_same_store(store.as_context().store_id(), self.store_id);
unsafe {
let mut tagged: ffi::M3TaggedValue = core::mem::zeroed();
Error::from_ffi(ffi::m3_GetGlobal(self.raw, &mut tagged))?;
let ty = ValType::from_ffi(tagged.type_)
.ok_or_else(|| Error::new("global has an unsupported value type"))?;
Ok(match ty {
ValType::I32 => Val::I32(tagged.value.i32_ as i32),
ValType::I64 => Val::I64(tagged.value.i64_ as i64),
ValType::F32 => Val::F32(tagged.value.f32_),
ValType::F64 => Val::F64(tagged.value.f64_),
})
}
}
pub fn set(&self, mut store: impl AsContextMut, value: Val) -> Result<()> {
assert_same_store(store.as_context_mut().store_id(), self.store_id);
let mut tagged = ffi::M3TaggedValue {
type_: value.ty().to_ffi(),
value: match value {
Val::I32(v) => ffi::M3TaggedValue_M3ValueUnion { i32_: v as u32 },
Val::I64(v) => ffi::M3TaggedValue_M3ValueUnion { i64_: v as u64 },
Val::F32(v) => ffi::M3TaggedValue_M3ValueUnion { f32_: v },
Val::F64(v) => ffi::M3TaggedValue_M3ValueUnion { f64_: v },
},
};
Error::from_ffi(unsafe { ffi::m3_SetGlobal(self.raw, &mut tagged) })
}
}