use std::ffi::{c_char, c_void};
#[repr(C)]
pub struct RuntimeHandle {
pub(crate) runtime_ptr: *mut c_void,
pub(crate) vtable: &'static RuntimeVTable,
}
#[repr(C)]
pub struct RuntimeVTable {
pub get_arg_f64: unsafe extern "C" fn(rt: *mut c_void, idx: u32) -> f64,
pub set_return_f64: unsafe extern "C" fn(rt: *mut c_void, idx: u32, value: f64),
pub get_arg_string: unsafe extern "C" fn(rt: *mut c_void, idx: u32) -> *const c_char,
pub get_arg_raw: unsafe extern "C" fn(rt: *mut c_void, idx: u32) -> u64,
pub resolve_closure: unsafe extern "C" fn(rt: *mut c_void, heap_handle: u64) -> u64,
pub execute_closure: unsafe extern "C" fn(rt: *mut c_void, closure_handle: u64) -> i64,
}
unsafe impl Send for RuntimeHandle {}
impl RuntimeHandle {
pub unsafe fn new(runtime_ptr: *mut c_void, vtable: &'static RuntimeVTable) -> Self {
Self {
runtime_ptr,
vtable,
}
}
#[inline]
pub fn get_arg_f64(&self, idx: u32) -> f64 {
unsafe { (self.vtable.get_arg_f64)(self.runtime_ptr, idx) }
}
#[inline]
pub fn set_return_f64(&mut self, idx: u32, value: f64) {
unsafe { (self.vtable.set_return_f64)(self.runtime_ptr, idx, value) }
}
pub fn get_arg_string(&self, idx: u32) -> Option<String> {
let ptr = unsafe { (self.vtable.get_arg_string)(self.runtime_ptr, idx) };
if ptr.is_null() {
None
} else {
Some(
unsafe { std::ffi::CStr::from_ptr(ptr) }
.to_string_lossy()
.into_owned(),
)
}
}
#[inline]
pub fn get_arg_raw(&self, idx: u32) -> u64 {
unsafe { (self.vtable.get_arg_raw)(self.runtime_ptr, idx) }
}
#[inline]
pub fn resolve_closure(&self, heap_handle: u64) -> u64 {
unsafe { (self.vtable.resolve_closure)(self.runtime_ptr, heap_handle) }
}
#[inline]
pub fn execute_closure(&mut self, closure_handle: u64) -> i64 {
unsafe { (self.vtable.execute_closure)(self.runtime_ptr, closure_handle) }
}
}