craft_eraser/
eref.rs

1//! Erased reference types, all are 3 pointers wide
2
3use core::fmt;
4use core::marker::PhantomData;
5use core::ptr::Pointee;
6
7use crate::ErasedNonNull;
8
9/// An erased reference, referencing a (possibly unsized) value of unknown type. Creating one is
10/// safe, but converting it back into any type is unsafe as it requires the user to know the type
11/// stored behind the reference.
12///
13/// This type will always be three pointers wide, even for sized types, due to needing to store
14/// an unknown metadata.
15pub struct ErasedRef<'a> {
16    ptr: ErasedNonNull,
17    _phantom: PhantomData<&'a ()>,
18}
19
20impl<'a> ErasedRef<'a> {
21    /// Create a new `ErasedRef` from a reference
22    pub fn new<T: ?Sized>(val: &'a T) -> ErasedRef<'a> {
23        ErasedRef {
24            ptr: ErasedNonNull::from(val),
25            _phantom: PhantomData,
26        }
27    }
28
29    /// Get the internal erased pointer of this reference
30    pub fn as_ptr(&self) -> &ErasedNonNull {
31        &self.ptr
32    }
33
34    /// Get back the reference stored in this `ErasedRef`
35    ///
36    /// # Safety
37    ///
38    /// The provided `T` must be the same type as originally stored in the reference
39    pub unsafe fn reify_ref<T: ?Sized + Pointee>(&self) -> &T {
40        self.ptr.reify_ptr::<T>().as_ref()
41    }
42}
43
44impl fmt::Pointer for ErasedRef<'_> {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        fmt::Pointer::fmt(&self.ptr, f)
47    }
48}
49
50impl fmt::Debug for ErasedRef<'_> {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        f.debug_struct("ErasedRef")
53            .field("ptr", &self.ptr)
54            .finish_non_exhaustive()
55    }
56}
57
58/// An erased mutable reference, referencing a (possibly unsized) value of unknown type. Creating
59/// one is safe, but converting it back into any type is unsafe as it requires the user to know the
60/// type stored behind the reference.
61///
62/// This type will always be three pointers wide, even for sized types, due to needing to store
63/// an unknown metadata.
64pub struct ErasedMut<'a> {
65    ptr: ErasedNonNull,
66    _phantom: PhantomData<&'a mut ()>,
67}
68
69impl<'a> ErasedMut<'a> {
70    /// Create a new `ErasedMute` from a reference
71    pub fn new<T: ?Sized>(val: &'a mut T) -> ErasedMut<'a> {
72        ErasedMut {
73            ptr: ErasedNonNull::from(val),
74            _phantom: PhantomData,
75        }
76    }
77
78    /// Get the internal erased pointer of this reference
79    pub fn as_ptr(&self) -> &ErasedNonNull {
80        &self.ptr
81    }
82
83    /// Get back the mutable reference stored in this `ErasedRef`
84    ///
85    /// # Safety
86    ///
87    /// The provided `T` must be the same type as originally stored in the reference
88    pub unsafe fn reify_ref<T: ?Sized + Pointee>(&mut self) -> &mut T {
89        self.ptr.reify_ptr::<T>().as_mut()
90    }
91}
92
93impl fmt::Pointer for ErasedMut<'_> {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        fmt::Pointer::fmt(&self.ptr, f)
96    }
97}
98
99impl fmt::Debug for ErasedMut<'_> {
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        f.debug_struct("ErasedRef")
102            .field("ptr", &self.ptr)
103            .finish_non_exhaustive()
104    }
105}