use crate::error::{Error, Result};
use crate::instance::Instance;
use crate::value::{GlobalType, Mutability, Val, ValType};
use core::marker::PhantomData;
use std::ffi::c_void;
pub struct Global<'a> {
content: ValType,
mutability: Mutability,
data: *mut c_void,
_marker: PhantomData<&'a Instance>,
}
impl<'a> Global<'a> {
pub(crate) fn new(content: ValType, mutability: Mutability, data: *mut c_void) -> Global<'a> {
Global {
content,
mutability,
data,
_marker: PhantomData,
}
}
pub fn ty(&self) -> GlobalType {
GlobalType::new(self.content, self.mutability)
}
pub fn get(&self) -> Val {
unsafe {
match self.content {
ValType::I32 => Val::I32((self.data as *const i32).read_unaligned()),
ValType::I64 => Val::I64((self.data as *const i64).read_unaligned()),
ValType::F32 => Val::F32((self.data as *const f32).read_unaligned()),
ValType::F64 => Val::F64((self.data as *const f64).read_unaligned()),
}
}
}
pub fn set(&mut self, new_val: Val) -> Result<()> {
if self.mutability == Mutability::Const {
return Err(Error::GlobalImmutable);
}
if new_val.ty() != self.content {
return Err(Error::TypeMismatch {
expected: self.content,
provided: new_val.ty(),
});
}
unsafe {
match new_val {
Val::I32(v) => (self.data as *mut i32).write_unaligned(v),
Val::I64(v) => (self.data as *mut i64).write_unaligned(v),
Val::F32(v) => (self.data as *mut f32).write_unaligned(v),
Val::F64(v) => (self.data as *mut f64).write_unaligned(v),
}
}
Ok(())
}
}
impl core::fmt::Debug for Global<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Global")
.field("ty", &self.ty())
.field("value", &self.get())
.finish()
}
}