use crate::error::{Error, Result};
use crate::instance::Instance;
use crate::value::{GlobalType, Mutability, Val};
use fizzyx_sys as sys;
use std::ffi::CString;
use std::mem::MaybeUninit;
#[derive(Debug, Clone)]
pub struct Global {
name: CString,
ty: GlobalType,
}
impl Global {
pub(crate) fn new(name: CString, ty: GlobalType) -> Self {
Self { name, ty }
}
pub fn ty(&self) -> GlobalType {
self.ty
}
pub fn get(&self, instance: &Instance) -> Val {
let value = self.resolve(instance);
let raw = unsafe { *value };
Val::from_sys(raw, self.ty.content())
}
pub fn set(&self, instance: &mut Instance, value: Val) -> Result<()> {
if self.ty.mutability() != Mutability::Mutable {
return Err(Error::GlobalImmutable);
}
if value.ty() != self.ty.content() {
return Err(Error::TypeMismatch {
index: 0,
expected: self.ty.content().name(),
found: value.ty().name(),
});
}
let ptr = self.resolve(instance);
unsafe { *ptr = value.to_sys() };
Ok(())
}
fn resolve(&self, instance: &Instance) -> *mut sys::FizzyValue {
let mut out = MaybeUninit::<sys::FizzyExternalGlobal>::uninit();
let found = unsafe {
sys::fizzy_find_exported_global(instance.as_ptr(), self.name.as_ptr(), out.as_mut_ptr())
};
debug_assert!(found, "exported global `{:?}` disappeared", self.name);
unsafe { out.assume_init() }.value
}
}