use core::marker::PhantomData;
use core::ptr::NonNull;
use crate::{
types::GcBoxInner,
{Gc, GcWeak},
};
#[macro_export]
macro_rules! unsize {
($gc:expr => $ty:ty) => {{
let gc = $gc;
unsafe {
$crate::__CoercePtrInternal::__coerce_unchecked(gc, |p: *mut _| -> *mut $ty { p })
}
}};
}
#[doc(hidden)]
pub unsafe trait __CoercePtrInternal<Dst> {
type FromPtr;
type ToPtr: ?Sized;
unsafe fn __coerce_unchecked<F>(self, coerce: F) -> Dst
where
F: FnOnce(*mut Self::FromPtr) -> *mut Self::ToPtr;
}
unsafe impl<'gc, T, U: ?Sized> __CoercePtrInternal<Gc<'gc, U>> for Gc<'gc, T> {
type FromPtr = T;
type ToPtr = U;
#[inline(always)]
unsafe fn __coerce_unchecked<F>(self, coerce: F) -> Gc<'gc, U>
where
F: FnOnce(*mut T) -> *mut U,
{
let ptr = self.ptr.as_ptr() as *mut T;
unsafe {
Gc {
ptr: NonNull::new_unchecked(coerce(ptr) as *mut GcBoxInner<U>),
_invariant: PhantomData,
}
}
}
}
unsafe impl<'gc, T, U: ?Sized> __CoercePtrInternal<GcWeak<'gc, U>> for GcWeak<'gc, T> {
type FromPtr = T;
type ToPtr = U;
#[inline(always)]
unsafe fn __coerce_unchecked<F>(self, coerce: F) -> GcWeak<'gc, U>
where
F: FnOnce(*mut T) -> *mut U,
{
unsafe {
let inner = self.inner.__coerce_unchecked(coerce);
GcWeak { inner }
}
}
}