#![no_std]
#![cfg_attr(feature = "any-ptr", allow(incomplete_features))]
#![cfg_attr(feature = "any-ptr", feature(generic_const_exprs, specialization))]
#![feature(unsize, ptr_metadata, exact_size_is_empty, trivial_bounds)]
#[cfg(not(feature = "any-ptr"))]
extern crate alloc;
mod impls;
#[cfg(not(feature = "any-ptr"))]
use alloc::boxed::Box;
use core::{
marker::Unsize,
mem::{self, ManuallyDrop},
ops::{Deref, DerefMut},
ptr::{self, Pointee},
};
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct PtrRepr(pub(self) *const ());
pub unsafe fn faith_metadata<Ptr, Dyn: ?Sized>(val: Ptr) -> (PtrRepr, <Dyn as Pointee>::Metadata)
where
Ptr: Unsize<Dyn>,
{
let val = &*ManuallyDrop::new(val);
(mem::transmute_copy(val), ptr::metadata(val as *const Dyn))
}
pub trait PointerLike<Dyn: ?Sized>: Sized {
fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata);
fn do_dyn(self) -> DynPtr<Dyn>
where
Self: Unsize<Dyn>,
{
unsafe { DynPtr::from_parts(faith_metadata::<_, Dyn>(self)) }
}
}
struct AlignOf<const N: usize>;
struct SizeOf<const N: usize>;
trait SamePtr {}
impl SamePtr for SizeOf<{ mem::size_of::<PtrRepr>() }> {}
impl SamePtr for AlignOf<{ mem::align_of::<PtrRepr>() }> {}
#[cfg(feature = "any-ptr")]
impl<Ptr, Dyn: ?Sized> PointerLike<Dyn> for Ptr
where
Ptr: Unsize<Dyn>,
SizeOf<{ mem::size_of::<Ptr>() }>: SamePtr,
AlignOf<{ mem::align_of::<Ptr>() }>: SamePtr,
{
fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
unsafe { faith_metadata::<_, Dyn>(self) }
}
}
#[cfg(not(feature = "any-ptr"))]
impl<T, Dyn: ?Sized> PointerLike<Dyn> for Box<T>
where
Self: Unsize<Dyn>,
{
fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
unsafe { faith_metadata::<_, Dyn>(self) }
}
}
#[cfg(not(feature = "any-ptr"))]
impl<Dyn: ?Sized> PointerLike<Dyn> for *const ()
where
Self: Unsize<Dyn>,
{
fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
unsafe { faith_metadata::<_, Dyn>(self) }
}
}
#[cfg(not(feature = "any-ptr"))]
impl<Dyn: ?Sized> PointerLike<Dyn> for usize
where
Self: Unsize<Dyn>,
{
fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
unsafe { faith_metadata::<_, Dyn>(self) }
}
}
#[repr(C)]
pub struct DynPtr<Dyn: ?Sized> {
repr: PtrRepr,
meta: <Dyn as Pointee>::Metadata,
}
unsafe impl<Dyn: ?Sized + Sync> Sync for DynPtr<Dyn> {}
unsafe impl<Dyn: ?Sized + Send> Send for DynPtr<Dyn> {}
impl<Dyn: ?Sized> DynPtr<Dyn> {
pub fn new<T>(val: T) -> Self
where
T: PointerLike<Dyn>,
{
unsafe { Self::from_parts(val.meta_repr()) }
}
pub unsafe fn from_parts((repr, meta): (PtrRepr, <Dyn as Pointee>::Metadata)) -> Self {
Self { repr, meta }
}
fn const_ptr(&self) -> *const Dyn {
ptr::from_raw_parts(ptr::addr_of!(self.repr).cast(), self.meta)
}
fn mut_ptr(&mut self) -> *mut Dyn {
ptr::from_raw_parts_mut(ptr::addr_of_mut!(self.repr).cast(), self.meta)
}
}
impl<Dyn: ?Sized> Deref for DynPtr<Dyn> {
type Target = Dyn;
fn deref(&self) -> &Self::Target {
unsafe { &*self.const_ptr() }
}
}
impl<Dyn: ?Sized> DerefMut for DynPtr<Dyn> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.mut_ptr() }
}
}
impl<Dyn: ?Sized> Drop for DynPtr<Dyn> {
fn drop(&mut self) {
unsafe { ptr::drop_in_place(self.mut_ptr()) }
}
}
pub type Dyn<Trait> = DynPtr<Trait>;