dyn_ptr/
lib.rs

1#![no_std]
2#![cfg_attr(feature = "any-ptr", allow(incomplete_features))]
3#![cfg_attr(feature = "any-ptr", feature(generic_const_exprs, specialization))]
4#![feature(unsize, ptr_metadata, exact_size_is_empty, trivial_bounds)]
5//#![feature(specialization)]
6
7#[cfg(not(feature = "any-ptr"))]
8extern crate alloc;
9
10mod impls;
11
12#[cfg(not(feature = "any-ptr"))]
13use alloc::boxed::Box;
14use core::{
15    marker::Unsize,
16    mem::{self, ManuallyDrop},
17    ops::{Deref, DerefMut},
18    ptr::{self, Pointee},
19};
20
21#[repr(transparent)]
22#[derive(Copy, Clone)]
23pub struct PtrRepr(pub(self) *const ());
24
25pub unsafe fn faith_metadata<Ptr, Dyn: ?Sized>(val: Ptr) -> (PtrRepr, <Dyn as Pointee>::Metadata)
26where
27    Ptr: Unsize<Dyn>,
28{
29    let val = &*ManuallyDrop::new(val);
30    (mem::transmute_copy(val), ptr::metadata(val as *const Dyn))
31}
32
33pub trait PointerLike<Dyn: ?Sized>: Sized {
34    fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata);
35
36    fn do_dyn(self) -> DynPtr<Dyn>
37    where
38        Self: Unsize<Dyn>,
39    {
40        // SAFETY: ...
41        unsafe { DynPtr::from_parts(faith_metadata::<_, Dyn>(self)) }
42    }
43}
44
45struct AlignOf<const N: usize>;
46struct SizeOf<const N: usize>;
47
48trait SamePtr {}
49
50impl SamePtr for SizeOf<{ mem::size_of::<PtrRepr>() }> {}
51impl SamePtr for AlignOf<{ mem::align_of::<PtrRepr>() }> {}
52
53#[cfg(feature = "any-ptr")]
54impl<Ptr, Dyn: ?Sized> PointerLike<Dyn> for Ptr
55where
56    Ptr: Unsize<Dyn>,
57    SizeOf<{ mem::size_of::<Ptr>() }>: SamePtr,
58    AlignOf<{ mem::align_of::<Ptr>() }>: SamePtr,
59{
60    fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
61        // SAFETY: `Ptr` has repr same as `ReprPtr` (aka `*const ()`)
62        unsafe { faith_metadata::<_, Dyn>(self) }
63    }
64}
65
66#[cfg(not(feature = "any-ptr"))]
67impl<T, Dyn: ?Sized> PointerLike<Dyn> for Box<T>
68where
69    Self: Unsize<Dyn>,
70{
71    fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
72        unsafe { faith_metadata::<_, Dyn>(self) }
73    }
74}
75
76#[cfg(not(feature = "any-ptr"))]
77impl<Dyn: ?Sized> PointerLike<Dyn> for *const ()
78where
79    Self: Unsize<Dyn>,
80{
81    fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
82        unsafe { faith_metadata::<_, Dyn>(self) }
83    }
84}
85
86#[cfg(not(feature = "any-ptr"))]
87impl<Dyn: ?Sized> PointerLike<Dyn> for usize
88where
89    Self: Unsize<Dyn>,
90{
91    fn meta_repr(self) -> (PtrRepr, <Dyn as Pointee>::Metadata) {
92        unsafe { faith_metadata::<_, Dyn>(self) }
93    }
94}
95
96#[repr(C)]
97pub struct DynPtr<Dyn: ?Sized> {
98    repr: PtrRepr,
99    meta: <Dyn as Pointee>::Metadata,
100}
101
102unsafe impl<Dyn: ?Sized + Sync> Sync for DynPtr<Dyn> {}
103unsafe impl<Dyn: ?Sized + Send> Send for DynPtr<Dyn> {}
104
105impl<Dyn: ?Sized> DynPtr<Dyn> {
106    pub fn new<T>(val: T) -> Self
107    where
108        T: PointerLike<Dyn>,
109    {
110        // SAFETY: `T` is guaranty has repr like pointer
111        unsafe { Self::from_parts(val.meta_repr()) }
112    }
113
114    pub unsafe fn from_parts((repr, meta): (PtrRepr, <Dyn as Pointee>::Metadata)) -> Self {
115        Self { repr, meta }
116    }
117
118    fn const_ptr(&self) -> *const Dyn {
119        ptr::from_raw_parts(ptr::addr_of!(self.repr).cast(), self.meta)
120    }
121
122    fn mut_ptr(&mut self) -> *mut Dyn {
123        ptr::from_raw_parts_mut(ptr::addr_of_mut!(self.repr).cast(), self.meta)
124    }
125}
126
127impl<Dyn: ?Sized> Deref for DynPtr<Dyn> {
128    type Target = Dyn;
129
130    fn deref(&self) -> &Self::Target {
131        unsafe { &*self.const_ptr() }
132    }
133}
134
135impl<Dyn: ?Sized> DerefMut for DynPtr<Dyn> {
136    fn deref_mut(&mut self) -> &mut Self::Target {
137        unsafe { &mut *self.mut_ptr() }
138    }
139}
140
141impl<Dyn: ?Sized> Drop for DynPtr<Dyn> {
142    fn drop(&mut self) {
143        unsafe { ptr::drop_in_place(self.mut_ptr()) }
144    }
145}
146
147pub type Dyn<Trait> = DynPtr<Trait>;