use crate::{
ElementSegment,
Func,
Global,
Handle,
Memory,
Table,
instance::handle::{AnyHandle, HasHandleKind},
memory::DataSegment,
store::StoreInner,
};
use core::{
marker::PhantomData,
ptr::{self, NonNull},
};
#[derive(Debug)]
pub struct AnyHandleAndEntity {
entity: NonNull<AnyEntity>,
handle: AnyHandle,
}
unsafe impl Send for AnyHandleAndEntity {}
unsafe impl Sync for AnyHandleAndEntity {}
impl AnyHandleAndEntity {
pub fn new(handle: AnyHandle) -> Self {
Self {
entity: NonNull::dangling(),
handle,
}
}
#[inline]
pub unsafe fn typed_ref<T: HasHandleKind>(&self) -> &HandleAndEntity<T> {
self.handle.assert_kind::<T>();
unsafe { &*ptr::from_ref(self).cast::<HandleAndEntity<T>>() }
}
#[inline]
pub unsafe fn typed_mut<T: HasHandleKind>(&mut self) -> &mut HandleAndEntity<T> {
self.handle.assert_kind::<T>();
unsafe { &mut *ptr::from_mut(self).cast::<HandleAndEntity<T>>() }
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct HandleAndEntity<T: Handle> {
inner: AnyHandleAndEntity,
marker: PhantomData<T>,
}
impl<T: Handle<Entity: Sized>> HandleAndEntity<T> {
#[inline]
pub fn entity(&self) -> NonNull<<T as Handle>::Entity> {
self.inner.entity.cast::<<T as Handle>::Entity>()
}
}
macro_rules! impl_handle_and_entity {
(
$(
impl HandleAndEntity<$handle:ident> {
cast: $cast:expr,
resolve: $resolve:expr,
}
)*
) => {
$(
impl HandleAndEntity<$handle> {
#[doc = concat!("Returns the [`", stringify!($handle), "`] handle of `self`.")]
#[inline]
pub fn handle(&self) -> $handle {
unsafe { $cast(self.inner.handle) }
}
#[inline]
pub(super) fn warmup(&mut self, store: &mut StoreInner) {
let handle = self.handle();
self.inner.entity = $resolve(store, &handle).cast::<AnyEntity>();
}
}
)*
};
}
impl_handle_and_entity! {
impl HandleAndEntity<Memory> {
cast: AnyHandle::cast_memory,
resolve: StoreInner::resolve_memory_ptr,
}
impl HandleAndEntity<Global> {
cast: AnyHandle::cast_global,
resolve: StoreInner::resolve_global_ptr,
}
impl HandleAndEntity<Table> {
cast: AnyHandle::cast_table,
resolve: StoreInner::resolve_table_ptr,
}
impl HandleAndEntity<Func> {
cast: AnyHandle::cast_func,
resolve: StoreInner::resolve_func_ptr,
}
impl HandleAndEntity<ElementSegment> {
cast: AnyHandle::cast_elem,
resolve: StoreInner::resolve_element_ptr,
}
impl HandleAndEntity<DataSegment> {
cast: AnyHandle::cast_data,
resolve: StoreInner::resolve_data_ptr,
}
}
#[derive(Debug)]
pub struct AnyEntity;