use crate::{GcHeap, GcStore, VMGcRef};
use wasmtime_environ::VMGcKind;
#[derive(Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct VMExternRef(VMGcRef);
impl std::fmt::Pointer for VMExternRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Pointer::fmt(&self.0, f)
}
}
impl From<VMExternRef> for VMGcRef {
#[inline]
fn from(x: VMExternRef) -> Self {
x.0
}
}
impl VMGcRef {
pub fn into_externref(self, gc_heap: &impl GcHeap) -> Result<VMExternRef, VMGcRef> {
if self.is_i31() {
return Err(self);
}
if gc_heap.header(&self).kind() == VMGcKind::ExternRef {
Ok(VMExternRef(self))
} else {
Err(self)
}
}
#[inline]
pub fn into_externref_unchecked(self) -> VMExternRef {
debug_assert!(!self.is_i31());
VMExternRef(self)
}
pub fn as_externref(&self, gc_heap: &impl GcHeap) -> Option<&VMExternRef> {
if self.is_i31() {
return None;
}
if gc_heap.header(&self).kind() == VMGcKind::ExternRef {
let ptr = self as *const VMGcRef;
let ret = unsafe { &*ptr.cast() };
assert!(matches!(ret, VMExternRef(VMGcRef { .. })));
Some(ret)
} else {
None
}
}
pub fn as_externref_unchecked(&self) -> &VMExternRef {
debug_assert!(!self.is_i31());
let ptr = self as *const VMGcRef;
let ret = unsafe { &*ptr.cast() };
assert!(matches!(ret, VMExternRef(VMGcRef { .. })));
ret
}
}
impl VMExternRef {
pub fn as_gc_ref(&self) -> &VMGcRef {
&self.0
}
pub fn clone(&self, gc_store: &mut GcStore) -> Self {
Self(gc_store.clone_gc_ref(&self.0))
}
pub fn drop(self, gc_store: &mut GcStore) {
gc_store.drop_gc_ref(self.0);
}
pub fn unchecked_copy(&self) -> Self {
Self(self.0.unchecked_copy())
}
}