Skip to main content

pstd/
boxed.rs

1use crate::alloc::{Allocator, Global};
2use std::{
3    alloc::Layout,
4    cmp::Ordering,
5    fmt,
6    hash::{Hash, Hasher},
7    ops::{Deref, DerefMut},
8    ptr,
9    ptr::NonNull,
10};
11
12/// A pointer type that uniquely owns a heap allocation of type `T`.
13///
14/// dyn values can be boxed using the [`unsize_box`](crate::unsize_box) macro.
15pub struct BoxA<T: ?Sized, A: Allocator> {
16    pub(crate) nn: NonNull<T>,
17    pub(crate) a: A,
18}
19
20/// Box allocated from Global.
21pub type Box<T> = BoxA<T, Global>;
22
23impl<T, A: Allocator> BoxA<T, A> {
24    /// Allocates memory then places t into it.
25    #[must_use]
26    pub fn new(t: T) -> Self
27    where
28        A: Default,
29    {
30        Self::new_in(t, A::default())
31    }
32
33    /// Allocates memory in the given allocator then places t into it.
34    pub fn new_in(t: T, a: A) -> Self {
35        let layout = Layout::new::<T>();
36        let nn = a.allocate(layout).unwrap();
37        let nn = unsafe { NonNull::<T>::new_unchecked(nn.as_ptr().cast::<T>()) };
38        unsafe {
39            ptr::write(nn.as_ptr(), t);
40        }
41        Self { nn, a }
42    }
43
44    /// Allocates memory in the given allocator then clones s into it.
45    pub fn from_slice_in(s: &[T], a: A) -> BoxA<[T], A>
46    where
47        T: Clone,
48    {
49        let n = s.len();
50        let layout = Layout::array::<T>(n).unwrap();
51        let nn = a.allocate(layout).unwrap();
52        let p = nn.as_ptr().cast::<T>();
53        for (i, e) in s.iter().enumerate() {
54            unsafe {
55                ptr::write(p.add(i), e.clone());
56            }
57        }
58        let nn = unsafe { NonNull::new_unchecked(p) };
59        let nn = NonNull::slice_from_raw_parts(nn, n);
60        BoxA::<[T], A> { nn, a }
61    }
62}
63
64impl<T: ?Sized, A: Allocator> BoxA<T, A> {
65    /// Allocates memory then copies s into it.
66    #[allow(clippy::should_implement_trait)]
67    pub fn from_str(s: &str) -> BoxA<str, A>
68    where
69        A: Default,
70    {
71        BoxA::<str, A>::from_str_in(s, A::default())
72    }
73
74    /// Allocates memory in the given allocator then copies s into it.
75    ///
76    /// Note: there is currently no equivalent in the standard library.
77    pub fn from_str_in(s: &str, a: A) -> BoxA<str, A> {
78        let n = s.len();
79        let layout = Layout::array::<u8>(n).unwrap();
80        let nn: NonNull<[u8]> = a.allocate(layout).unwrap();
81        let p: *mut u8 = nn.as_ptr().cast::<u8>();
82
83        unsafe {
84            ptr::copy_nonoverlapping(s.as_ptr(), p, n);
85        }
86
87        // Need to trim any over-allocation!
88        let p = unsafe { std::slice::from_raw_parts_mut(p, n) };
89        let nn: NonNull<[u8]> = unsafe { NonNull::new_unchecked(p) };
90        let p: *mut str = nn.as_ptr() as *mut str;
91        let nn: NonNull<str> = unsafe { NonNull::new_unchecked(p) };
92
93        BoxA::<str, A> { nn, a }
94    }
95
96    /// Convert into raw pointer and allocator.
97    pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
98        let mut b = std::mem::ManuallyDrop::new(b);
99        let p = &raw mut **b;
100        let a = unsafe { ptr::read(&b.a) };
101        (p, a)
102    }
103
104    /// Create from raw pointer in specified allocator.
105    ///
106    /// # Safety
107    ///
108    /// This function is unsafe because improper use may lead to
109    /// memory problems. For example, a double-free may occur if the
110    /// function is called twice on the same raw pointer.
111    ///
112    /// The non-null pointer must point to a block of memory allocated by `a`.
113    pub unsafe fn from_raw_in(p: *mut T, a: A) -> Self {
114        let nn = unsafe { NonNull::new_unchecked(p) };
115        Self { nn, a }
116    }
117
118    fn r(&self) -> &T {
119        unsafe { &*self.nn.as_ptr() }
120    }
121}
122
123impl<A: Allocator + Clone> Clone for BoxA<str, A> {
124    fn clone(&self) -> BoxA<str, A> {
125        BoxA::<str, A>::from_str_in(self, self.a.clone())
126    }
127}
128
129impl<T:Clone, A: Allocator + Clone> Clone for BoxA<T, A> {
130    fn clone(&self) -> BoxA<T, A> {
131        
132        let p = self.nn.as_ptr();
133        let v = unsafe{ (*p).clone() };
134        BoxA::new_in( v, self.a.clone() )
135    }
136}
137
138impl<T: ?Sized + Hash, A: Allocator> Hash for BoxA<T, A> {
139    fn hash<H: Hasher>(&self, state: &mut H) {
140        (**self).hash(state);
141    }
142}
143
144impl<T: ?Sized + Eq, A: Allocator> Eq for BoxA<T, A> {}
145
146impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for BoxA<T, A> {
147    fn eq(&self, other: &Self) -> bool {
148        PartialEq::eq(&**self, &**other)
149    }
150}
151
152impl<T: ?Sized + Ord, A: Allocator> Ord for BoxA<T, A> {
153    fn cmp(&self, other: &Self) -> Ordering {
154        Ord::cmp(&**self, &**other)
155    }
156}
157
158impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for BoxA<T, A> {
159    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
160        PartialOrd::partial_cmp(&**self, &**other)
161    }
162}
163
164unsafe impl<T: ?Sized + Send, A: Allocator + Send> Send for BoxA<T, A> {}
165unsafe impl<T: ?Sized + Sync, A: Allocator + Sync> Sync for BoxA<T, A> {}
166
167impl<T: ?Sized, A: Allocator> Drop for BoxA<T, A> {
168    fn drop(&mut self) {
169        unsafe {
170            let layout = Layout::for_value(&*self.nn.as_ptr());
171            self.nn.drop_in_place();
172            let p = NonNull::new(self.nn.as_ptr().cast::<u8>()).unwrap();
173            self.a.deallocate(p, layout);
174        }
175    }
176}
177
178impl<T: ?Sized, A: Allocator> Deref for BoxA<T, A> {
179    type Target = T;
180
181    fn deref(&self) -> &T {
182        self.r()
183    }
184}
185
186impl<T: ?Sized, A: Allocator> DerefMut for BoxA<T, A> {
187    fn deref_mut(&mut self) -> &mut T {
188        unsafe { &mut *self.nn.as_ptr() }
189    }
190}
191
192impl<T: ?Sized + fmt::Display, A: Allocator> fmt::Display for BoxA<T, A> {
193    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194        fmt::Display::fmt(self.r(), f)
195    }
196}
197
198impl<T: ?Sized + fmt::Debug, A: Allocator> fmt::Debug for BoxA<T, A> {
199    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200        fmt::Debug::fmt(self.r(), f)
201    }
202}
203
204use std::borrow::Borrow;
205impl<T: ?Sized, A: Allocator> Borrow<T> for BoxA<T, A> {
206    fn borrow(&self) -> &T {
207        self
208    }
209}
210
211use std::borrow::BorrowMut;
212impl<T: ?Sized, A: Allocator> BorrowMut<T> for BoxA<T, A> {
213    fn borrow_mut(&mut self) -> &mut T {
214        self
215    }
216}
217
218#[cfg(feature = "dynbox")]
219use std::{marker::Unsize, ops::CoerceUnsized};
220
221#[cfg(feature = "dynbox")]
222impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<BoxA<U, A>> for BoxA<T, A> {}
223
224/// Macro to unsize a box.
225///
226/// # Example
227/// ```
228/// use pstd::{BoxA, unsize_box, localalloc::Local};
229/// trait MyTrait {}
230/// struct MyStruct; impl MyTrait for MyStruct{}
231/// type LBox<T> = BoxA<T, Local>;
232/// let b : LBox<dyn MyTrait> = unsize_box!( LBox::new(MyStruct{}) );
233/// ```
234#[macro_export]
235macro_rules! unsize_box {
236    ( $boxed:expr ) => {{
237        let (ptr, allocator) = $crate::BoxA::into_raw_with_allocator($boxed);
238        let ptr: *mut _ = ptr;
239        unsafe { $crate::BoxA::from_raw_in(ptr, allocator) }
240    }};
241}
242
243#[cfg(feature = "serde")]
244impl<T, A> serde::Serialize for BoxA<T, A>
245where
246    T: serde::Serialize,
247    A: Allocator,
248{
249    #[inline(always)]
250    fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
251        (**self).serialize(serializer)
252    }
253}
254
255#[cfg(feature = "serde")]
256impl<'de, T, A:Allocator + Default> serde::Deserialize<'de> for BoxA<T, A>
257where
258    T: serde::Deserialize<'de>,
259    A: Allocator + Default,
260{
261    #[inline(always)]
262    fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
263        let value = T::deserialize(deserializer)?;
264        Ok(BoxA::new(value))
265    }
266}