aliasable/
boxed.rs

1//! Aliasable `Box`.
2
3use core::ops::{Deref, DerefMut};
4use core::pin::Pin;
5use core::ptr::NonNull;
6use core::{fmt, mem};
7
8pub use alloc::boxed::Box as UniqueBox;
9
10/// Basic aliasable (non `core::ptr::Unique`) alternative to
11/// [`alloc::boxed::Box`].
12pub struct AliasableBox<T: ?Sized>(NonNull<T>);
13
14impl<T: ?Sized> AliasableBox<T> {
15    /// Construct an `AliasableBox` from a [`UniqueBox`].
16    pub fn from_unique(ptr: UniqueBox<T>) -> Self {
17        let ptr = unsafe { NonNull::new_unchecked(UniqueBox::into_raw(ptr)) };
18        Self(ptr)
19    }
20
21    /// Consumes `self` and converts it into a non-aliasable [`UniqueBox`].
22    #[inline]
23    pub fn into_unique(mut ptr: AliasableBox<T>) -> UniqueBox<T> {
24        // As we are consuming the `Box` structure we can safely assume any
25        // aliasing has ended and convert the aliasable `Box` back to into an
26        // unaliasable `UniqueBox`.
27        let unique = unsafe { ptr.reclaim_as_unique_box() };
28        // Forget the aliasable `Box` so the allocation behind the `UniqueBox`
29        // is not deallocated.
30        mem::forget(ptr);
31        // Return the `UniqueBox`.
32        unique
33    }
34
35    /// Convert a pinned [`AliasableBox`] to a `core::ptr::Unique` backed pinned
36    /// [`UniqueBox`].
37    pub fn into_unique_pin(pin: Pin<AliasableBox<T>>) -> Pin<UniqueBox<T>> {
38        // SAFETY: The pointer is not changed, just the container.
39        unsafe {
40            let aliasable = Pin::into_inner_unchecked(pin);
41            Pin::new_unchecked(AliasableBox::into_unique(aliasable))
42        }
43    }
44
45    /// Convert a pinned `core::ptr::Unique` backed [`UniqueBox`] to a
46    /// pinned [`AliasableBox`].
47    pub fn from_unique_pin(pin: Pin<UniqueBox<T>>) -> Pin<AliasableBox<T>> {
48        // SAFETY: The pointer is not changed, just the container.
49        unsafe {
50            let unique = Pin::into_inner_unchecked(pin);
51            Pin::new_unchecked(AliasableBox::from(unique))
52        }
53    }
54
55    #[inline]
56    unsafe fn reclaim_as_unique_box(&mut self) -> UniqueBox<T> {
57        UniqueBox::from_raw(self.0.as_ptr())
58    }
59}
60
61impl<T: ?Sized> From<UniqueBox<T>> for AliasableBox<T> {
62    fn from(ptr: UniqueBox<T>) -> Self {
63        Self::from_unique(ptr)
64    }
65}
66
67impl<T: ?Sized> Drop for AliasableBox<T> {
68    fn drop(&mut self) {
69        // SAFETY: As `self` is being dropped we can safely assume any aliasing
70        // has ended and convert the `AliasableBox` back to into an unaliasable
71        // `UniqueBox` to handle the deallocation.
72        let _ = unsafe { self.reclaim_as_unique_box() };
73    }
74}
75
76impl<T: ?Sized> Deref for AliasableBox<T> {
77    type Target = T;
78
79    #[inline]
80    fn deref(&self) -> &T {
81        // SAFETY: We own the data, so we can return a reference to it.
82        unsafe { self.0.as_ref() }
83    }
84}
85
86impl<T: ?Sized> DerefMut for AliasableBox<T> {
87    #[inline]
88    fn deref_mut(&mut self) -> &mut T {
89        // SAFETY: We own the data, so we can return a reference to it.
90        unsafe { self.0.as_mut() }
91    }
92}
93
94impl<T: ?Sized> AsRef<T> for AliasableBox<T> {
95    #[inline]
96    fn as_ref(&self) -> &T {
97        &*self
98    }
99}
100
101impl<T: ?Sized> AsMut<T> for AliasableBox<T> {
102    fn as_mut(&mut self) -> &mut T {
103        &mut *self
104    }
105}
106
107impl<T: ?Sized> fmt::Debug for AliasableBox<T>
108where
109    T: fmt::Debug,
110{
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        fmt::Debug::fmt(self.as_ref(), f)
113    }
114}
115
116unsafe impl<T: ?Sized> Send for AliasableBox<T> where T: Send {}
117unsafe impl<T: ?Sized> Sync for AliasableBox<T> where T: Sync {}
118
119#[cfg(feature = "traits")]
120unsafe impl<T: ?Sized> crate::StableDeref for AliasableBox<T> {}
121
122#[cfg(feature = "traits")]
123unsafe impl<T: ?Sized> crate::AliasableDeref for AliasableBox<T> {}
124
125#[cfg(test)]
126mod tests {
127    use super::{AliasableBox, UniqueBox};
128    use alloc::format;
129
130    #[test]
131    fn test_new() {
132        let aliasable = AliasableBox::from_unique(UniqueBox::new(10));
133        assert_eq!(*aliasable, 10);
134        let unique = AliasableBox::into_unique(aliasable);
135        assert_eq!(*unique, 10);
136    }
137
138    #[test]
139    fn test_new_pin() {
140        let aliasable = AliasableBox::from_unique_pin(UniqueBox::pin(10));
141        assert_eq!(*aliasable, 10);
142        let unique = AliasableBox::into_unique_pin(aliasable);
143        assert_eq!(*unique, 10);
144    }
145
146    #[test]
147    fn test_refs() {
148        let mut aliasable = AliasableBox::from_unique(UniqueBox::new(10));
149        let ptr: *const u8 = &*aliasable;
150        let as_mut_ptr: *const u8 = aliasable.as_mut();
151        let as_ref_ptr: *const u8 = aliasable.as_ref();
152        assert_eq!(ptr, as_mut_ptr);
153        assert_eq!(ptr, as_ref_ptr);
154    }
155
156    #[test]
157    fn test_debug() {
158        let aliasable = AliasableBox::from_unique(UniqueBox::new(10));
159        assert_eq!(format!("{:?}", aliasable), "10");
160    }
161}