use super::{VMArrayCallNative, VMOpaqueContext};
use crate::error::OutOfMemory;
use crate::prelude::*;
use crate::runtime::vm::{StoreBox, VMFuncRef};
use core::any::Any;
use core::ptr::NonNull;
use wasmtime_environ::{VM_ARRAY_CALL_HOST_FUNC_MAGIC, VMSharedTypeIndex};
#[repr(C)]
pub struct VMArrayCallHostFuncContext {
magic: u32,
pub(crate) func_ref: VMFuncRef,
host_state: Box<dyn Any + Send + Sync>,
}
impl VMArrayCallHostFuncContext {
pub unsafe fn new(
host_func: VMArrayCallNative,
type_index: VMSharedTypeIndex,
host_state: Box<dyn Any + Send + Sync>,
) -> Result<StoreBox<VMArrayCallHostFuncContext>, OutOfMemory> {
let ctx = StoreBox::new(VMArrayCallHostFuncContext {
magic: wasmtime_environ::VM_ARRAY_CALL_HOST_FUNC_MAGIC,
func_ref: VMFuncRef {
array_call: NonNull::new(host_func as *mut u8).unwrap().cast().into(),
type_index,
wasm_call: None,
vmctx: NonNull::dangling().into(),
},
host_state,
})?;
let vmctx = VMOpaqueContext::from_vm_array_call_host_func_context(ctx.get());
unsafe {
ctx.get().as_mut().func_ref.vmctx = vmctx.into();
}
Ok(ctx)
}
#[inline]
pub fn host_state(&self) -> &(dyn Any + Send + Sync) {
&*self.host_state
}
#[inline]
pub fn func_ref(&self) -> &VMFuncRef {
&self.func_ref
}
#[inline]
pub unsafe fn from_opaque(
opaque: NonNull<VMOpaqueContext>,
) -> NonNull<VMArrayCallHostFuncContext> {
unsafe {
debug_assert_eq!(opaque.as_ref().magic, VM_ARRAY_CALL_HOST_FUNC_MAGIC);
}
opaque.cast()
}
}
#[test]
fn vmarray_call_host_func_context_offsets() {
use core::mem::offset_of;
use wasmtime_environ::{HostPtr, PtrSize};
assert_eq!(
usize::from(HostPtr.vmarray_call_host_func_context_func_ref()),
offset_of!(VMArrayCallHostFuncContext, func_ref)
);
}