use crate::func::Func;
use crate::global::Global;
use crate::memory::Memory;
use crate::trampoline::HostFunc;
use crate::value::{FuncType, GlobalType};
use fizzyx_sys as sys;
use std::ffi::CString;
use std::mem::MaybeUninit;
use std::rc::Rc;
pub struct Instance {
inner: *mut sys::FizzyInstance,
_keepalive: Vec<Rc<HostFunc>>,
}
impl Instance {
pub(crate) unsafe fn from_raw(
inner: *mut sys::FizzyInstance,
keepalive: Vec<Rc<HostFunc>>,
) -> Self {
Self {
inner,
_keepalive: keepalive,
}
}
pub(crate) fn as_ptr(&self) -> *mut sys::FizzyInstance {
self.inner
}
pub fn get_func(&self, name: &str) -> Option<Func> {
let c_name = CString::new(name).ok()?;
let module = unsafe { sys::fizzy_get_instance_module(self.inner) };
let mut idx = 0u32;
let found =
unsafe { sys::fizzy_find_exported_function_index(module, c_name.as_ptr(), &mut idx) };
if !found {
return None;
}
let raw = unsafe { sys::fizzy_get_function_type(module, idx) };
let ty = FuncType::from_sys(&raw).ok()?;
Some(Func::new(idx, ty))
}
pub fn get_memory(&self, name: &str) -> Option<Memory> {
let c_name = CString::new(name).ok()?;
let mut out = MaybeUninit::<sys::FizzyExternalMemory>::uninit();
let found = unsafe {
sys::fizzy_find_exported_memory(self.inner, c_name.as_ptr(), out.as_mut_ptr())
};
found.then(Memory::new)
}
pub fn get_global(&self, name: &str) -> Option<Global> {
let c_name = CString::new(name).ok()?;
let mut out = MaybeUninit::<sys::FizzyExternalGlobal>::uninit();
let found = unsafe {
sys::fizzy_find_exported_global(self.inner, c_name.as_ptr(), out.as_mut_ptr())
};
if !found {
return None;
}
let out = unsafe { out.assume_init() };
let ty = GlobalType::from_sys(out.type_).ok()?;
Some(Global::new(c_name, ty))
}
}
impl Drop for Instance {
fn drop(&mut self) {
unsafe { sys::fizzy_free_instance(self.inner) }
}
}