1use ::core::{fmt, mem::transmute};
4use ptr_meta::{from_raw_parts_mut, metadata, DynMetadata, Pointee};
5
6#[derive(Clone, Copy)]
8pub union Metadata {
9 unit: (),
10 usize: usize,
11 vtable: DynMetadata<()>,
12}
13
14impl fmt::Debug for Metadata {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 write!(f, "<metadata>")
17 }
18}
19
20impl From<()> for Metadata {
21 fn from(value: ()) -> Self {
22 Self { unit: value }
23 }
24}
25
26impl From<usize> for Metadata {
27 fn from(value: usize) -> Self {
28 Self { usize: value }
29 }
30}
31
32impl<T: ?Sized> From<DynMetadata<T>> for Metadata {
33 fn from(value: DynMetadata<T>) -> Self {
34 Self {
35 vtable: unsafe {
36 transmute::<DynMetadata<T>, DynMetadata<()>>(value)
37 },
38 }
39 }
40}
41
42pub trait FromMetadata {
44 unsafe fn from_metadata(metadata: Metadata) -> Self;
51}
52
53impl FromMetadata for () {
54 unsafe fn from_metadata(metadata: Metadata) -> Self {
55 unsafe { metadata.unit }
56 }
57}
58
59impl FromMetadata for usize {
60 unsafe fn from_metadata(metadata: Metadata) -> Self {
61 unsafe { metadata.usize }
62 }
63}
64
65impl<T: ?Sized> FromMetadata for DynMetadata<T> {
66 unsafe fn from_metadata(metadata: Metadata) -> Self {
67 unsafe { transmute::<DynMetadata<()>, DynMetadata<T>>(metadata.vtable) }
68 }
69}
70
71#[derive(Clone, Copy, Debug)]
73pub struct ErasedPtr {
74 data_address: *mut (),
75 metadata: Metadata,
76}
77
78impl ErasedPtr {
79 #[inline]
81 pub fn new<T>(ptr: *mut T) -> Self
82 where
83 T: Pointee + ?Sized,
84 T::Metadata: Into<Metadata>,
85 {
86 Self {
87 data_address: ptr.cast(),
88 metadata: metadata(ptr).into(),
89 }
90 }
91
92 #[inline]
94 pub fn data_address(&self) -> *mut () {
95 self.data_address
96 }
97
98 #[inline]
100 pub fn metadata(&self) -> Metadata {
101 self.metadata
102 }
103
104 #[inline]
108 pub unsafe fn downcast_unchecked<T>(&self) -> *mut T
109 where
110 T: Pointee + ?Sized,
111 T::Metadata: FromMetadata,
112 {
113 from_raw_parts_mut(self.data_address, unsafe {
114 T::Metadata::from_metadata(self.metadata)
115 })
116 }
117}