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
12pub struct BoxA<T: ?Sized, A: Allocator> {
16 pub(crate) nn: NonNull<T>,
17 pub(crate) a: A,
18}
19
20pub type Box<T> = BoxA<T, Global>;
22
23impl<T, A: Allocator> BoxA<T, A> {
24 #[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 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 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 #[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 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 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 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 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_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}