use crate::ptr_meta::{DynMetadata, Pointee};
use crate::runtime::ErasedDestructorContext;
use core::alloc::Layout;
#[doc(hidden)]
pub trait SupportedPointee: SupportedPointeeInternal {}
#[doc(hidden)]
pub trait SupportedWeakPointee: SupportedPointee + SupportedWeakPointeeInternal {}
pub trait SupportedPointeeInternal: Pointee<Metadata: SupportedMetadata> {}
impl<T: ?Sized + Pointee> SupportedPointeeInternal for T where T::Metadata: SupportedMetadata {}
impl<T: ?Sized + Pointee> super::SupportedPointee for T where T::Metadata: SupportedMetadata {}
pub trait SupportedWeakPointeeInternal: SupportedPointeeInternal {
unsafe fn layout_for_ptr(ptr: *mut Self) -> Layout;
}
#[cfg(feature = "nightly-ptr-layout")]
mod nightly_weak_pointee {
use super::{Layout, Pointee, SupportedMetadata, SupportedWeakPointeeInternal};
use crate::SupportedWeakPointee;
impl<T: ?Sized + Pointee> SupportedWeakPointeeInternal for T
where
T::Metadata: SupportedMetadata,
{
#[inline]
unsafe fn layout_for_ptr(ptr: *mut Self) -> Layout {
unsafe { Layout::for_value_raw(ptr.cast_const()) }
}
}
impl<T: ?Sized + Pointee> SupportedWeakPointee for T where T::Metadata: SupportedMetadata {}
}
#[cfg(not(feature = "nightly-ptr-layout"))]
mod stable_weak_pointee {
use super::{Layout, SupportedWeakPointeeInternal};
use crate::SupportedWeakPointee;
impl<T> SupportedWeakPointee for T {}
#[cfg(not(feature = "nightly-ptr-layout"))]
impl<T> SupportedWeakPointeeInternal for T {
#[inline]
unsafe fn layout_for_ptr(ptr: *mut Self) -> Layout {
let _ = ptr;
Layout::new::<T>()
}
}
impl<T> SupportedWeakPointeeInternal for [T] {
#[inline]
unsafe fn layout_for_ptr(ptr: *mut Self) -> Layout {
unsafe { Layout::array::<T>(ptr.len()).unwrap_unchecked() }
}
}
impl<T> SupportedWeakPointee for [T] {}
macro_rules! weak_pointee_str_like {
($($target:ty),*) => {
$(impl SupportedWeakPointeeInternal for $target {
#[inline]
unsafe fn layout_for_ptr(ptr: *mut Self) -> Layout {
unsafe { SupportedWeakPointeeInternal::layout_for_ptr(ptr as *mut [u8]) }
}
}
impl SupportedWeakPointee for $target {})*
};
}
weak_pointee_str_like!(str, std::ffi::OsStr, core::ffi::CStr);
}
pub trait SupportedMetadata: Copy {
fn to_context(self) -> ErasedDestructorContext;
unsafe fn from_context(ctx: ErasedDestructorContext) -> Self;
}
impl SupportedMetadata for usize {
#[inline]
fn to_context(self) -> ErasedDestructorContext {
ErasedDestructorContext(core::ptr::without_provenance_mut(self))
}
#[inline]
unsafe fn from_context(ctx: ErasedDestructorContext) -> Self {
ctx.0.addr()
}
}
impl SupportedMetadata for () {
#[inline]
fn to_context(self) -> ErasedDestructorContext {
ErasedDestructorContext(core::ptr::null_mut())
}
#[inline(always)]
unsafe fn from_context(_ctx: ErasedDestructorContext) -> Self {
}
}
impl<Dyn: ?Sized> SupportedMetadata for DynMetadata<Dyn> {
#[inline]
fn to_context(self) -> ErasedDestructorContext {
unsafe { core::mem::transmute::<DynMetadata<Dyn>, ErasedDestructorContext>(self) }
}
#[inline]
unsafe fn from_context(ctx: ErasedDestructorContext) -> Self {
unsafe { core::mem::transmute::<ErasedDestructorContext, DynMetadata<Dyn>>(ctx) }
}
}