1use crate::{unreachable_unchecked, IntoDyn};
16
17use super::{vec::*, AllocPtr, AllocSlice, IAlloc};
18use core::{
19 fmt::Debug,
20 mem::{ManuallyDrop, MaybeUninit},
21 ptr::NonNull,
22};
23
24#[crate::stabby]
26pub struct Box<T, Alloc: IAlloc = super::DefaultAllocator> {
27 ptr: AllocPtr<T, Alloc>,
28}
29unsafe impl<T: Send, Alloc: IAlloc + Send> Send for Box<T, Alloc> {}
31unsafe impl<T: Sync, Alloc: IAlloc> Sync for Box<T, Alloc> {}
33unsafe impl<T: Send, Alloc: IAlloc + Send> Send for BoxedSlice<T, Alloc> {}
35unsafe impl<T: Sync, Alloc: IAlloc> Sync for BoxedSlice<T, Alloc> {}
37
38#[cfg(not(stabby_default_alloc = "disabled"))]
39impl<T> Box<T> {
40 pub unsafe fn make<
55 F: for<'a> FnOnce(&'a mut core::mem::MaybeUninit<T>) -> Result<&'a mut T, ()>,
56 >(
57 constructor: F,
58 ) -> Result<Self, Box<MaybeUninit<T>>> {
59 unsafe { Self::make_in(constructor, super::DefaultAllocator::new()) }
61 }
62 pub fn new(value: T) -> Self {
67 Self::new_in(value, super::DefaultAllocator::new())
68 }
69}
70impl<T, Alloc: IAlloc> Box<T, Alloc> {
71 #[allow(clippy::type_complexity)]
87 pub unsafe fn try_make_in<
88 F: for<'a> FnOnce(&'a mut core::mem::MaybeUninit<T>) -> Result<&'a mut T, ()>,
89 >(
90 constructor: F,
91 mut alloc: Alloc,
92 ) -> Result<Self, Result<Box<MaybeUninit<T>, Alloc>, (F, Alloc)>> {
93 let mut ptr = match AllocPtr::alloc(&mut alloc) {
94 Some(mut ptr) => {
95 unsafe { ptr.prefix_mut() }.alloc.write(alloc);
97 ptr
98 }
99 None => return Err(Err((constructor, alloc))),
100 };
101 constructor(unsafe { ptr.as_mut() }).map_or_else(
103 |()| Err(Ok(Box { ptr })),
104 |_| {
105 Ok(Self {
106 ptr: unsafe { ptr.assume_init() },
108 })
109 },
110 )
111 }
112 pub fn try_new_in(value: T, alloc: Alloc) -> Result<Self, (T, Alloc)> {
116 let this = unsafe {
118 Self::try_make_in(
119 |slot: &mut core::mem::MaybeUninit<T>| {
120 Ok(slot.write(core::ptr::read(&value)))
122 },
123 alloc,
124 )
125 };
126 match this {
127 Ok(this) => {
128 core::mem::forget(value);
129 Ok(this)
130 }
131 Err(Err((_, a))) => Err((value, a)),
132 Err(Ok(_)) => unsafe { unreachable_unchecked!() },
134 }
135 }
136 pub unsafe fn make_in<
149 F: for<'a> FnOnce(&'a mut core::mem::MaybeUninit<T>) -> Result<&'a mut T, ()>,
150 >(
151 constructor: F,
152 alloc: Alloc,
153 ) -> Result<Self, Box<MaybeUninit<T>, Alloc>> {
154 Self::try_make_in(constructor, alloc).map_err(|e| match e {
155 Ok(uninit) => uninit,
156 Err(_) => panic!("Allocation failed"),
157 })
158 }
159 pub fn new_in(value: T, alloc: Alloc) -> Self {
164 let this = unsafe { Self::make_in(move |slot| Ok(slot.write(value)), alloc) };
166 unsafe { this.unwrap_unchecked() }
168 }
169 pub fn into_inner(this: Self) -> T {
171 let mut this = core::mem::ManuallyDrop::new(this);
172 let ret = ManuallyDrop::new(unsafe { core::ptr::read(&**this) });
174 unsafe { this.free() };
176 ManuallyDrop::into_inner(ret)
177 }
178 pub const fn into_raw(this: Self) -> AllocPtr<T, Alloc> {
182 let inner = this.ptr;
183 core::mem::forget(this);
184 inner
185 }
186 pub const unsafe fn from_raw(this: AllocPtr<T, Alloc>) -> Self {
190 Self { ptr: this }
191 }
192}
193
194impl<T, Alloc: IAlloc> Box<T, Alloc> {
195 unsafe fn free(&mut self) {
199 let mut alloc = unsafe { self.ptr.prefix().alloc.assume_init_read() };
201 unsafe { self.ptr.free(&mut alloc) }
203 }
204}
205
206impl<T: Clone, Alloc: IAlloc + Clone> Clone for Box<T, Alloc> {
207 fn clone(&self) -> Self {
208 Box::new_in(
209 T::clone(self),
210 unsafe { self.ptr.prefix().alloc.assume_init_ref() }.clone(),
211 )
212 }
213}
214impl<T, Alloc: IAlloc> core::ops::Deref for Box<T, Alloc> {
215 type Target = T;
216 fn deref(&self) -> &Self::Target {
217 unsafe { self.ptr.as_ref() }
218 }
219}
220
221impl<T, Alloc: IAlloc> core::ops::DerefMut for Box<T, Alloc> {
222 fn deref_mut(&mut self) -> &mut Self::Target {
223 unsafe { self.ptr.as_mut() }
224 }
225}
226impl<T, Alloc: IAlloc> crate::IPtr for Box<T, Alloc> {
227 unsafe fn as_ref<U: Sized>(&self) -> &U {
228 self.ptr.cast().as_ref()
229 }
230}
231impl<T, Alloc: IAlloc> crate::IPtrMut for Box<T, Alloc> {
232 unsafe fn as_mut<U: Sized>(&mut self) -> &mut U {
233 self.ptr.cast().as_mut()
234 }
235}
236impl<T, Alloc: IAlloc> crate::IPtrOwned for Box<T, Alloc> {
237 fn drop(this: &mut core::mem::ManuallyDrop<Self>, drop: unsafe extern "C" fn(&mut ())) {
238 let rthis = &mut ***this;
239 unsafe {
241 drop(core::mem::transmute::<&mut T, &mut ()>(rthis));
242 }
243 unsafe { this.free() }
245 }
246}
247impl<T, Alloc: IAlloc> Drop for Box<T, Alloc> {
248 fn drop(&mut self) {
249 unsafe {
251 core::ptr::drop_in_place(self.ptr.as_mut());
252 }
253 unsafe { self.free() }
255 }
256}
257impl<T, Alloc: IAlloc> IntoDyn for Box<T, Alloc> {
258 type Anonymized = Box<(), Alloc>;
259 type Target = T;
260 fn anonimize(self) -> Self::Anonymized {
261 let original_prefix = self.ptr.prefix_ptr();
262 let anonymized = unsafe { core::mem::transmute::<Self, Self::Anonymized>(self) };
264 let anonymized_prefix = anonymized.ptr.prefix_ptr();
265 assert_eq!(anonymized_prefix, original_prefix, "The allocation prefix was lost in anonimization, this is definitely a bug, please report it.");
266 anonymized
267 }
268}
269
270#[crate::stabby]
278pub struct BoxedSlice<T, Alloc: IAlloc = super::DefaultAllocator> {
279 pub(crate) slice: AllocSlice<T, Alloc>,
280 pub(crate) alloc: Alloc,
281}
282impl<T, Alloc: IAlloc> BoxedSlice<T, Alloc> {
283 pub fn with_capacity_in(capacity: usize, alloc: Alloc) -> Self {
285 Vec::with_capacity_in(capacity, alloc).into()
286 }
287 pub const fn len(&self) -> usize {
289 ptr_diff(self.slice.end, self.slice.start.ptr)
290 }
291 pub const fn is_empty(&self) -> bool {
293 self.len() == 0
294 }
295 pub fn as_slice(&self) -> &[T] {
297 unsafe { core::slice::from_raw_parts(self.slice.start.as_ptr(), self.len()) }
299 }
300 pub fn as_slice_mut(&mut self) -> &mut [T] {
302 unsafe { core::slice::from_raw_parts_mut(self.slice.start.as_ptr(), self.len()) }
304 }
305 pub fn try_push(&mut self, value: T) -> Result<(), T> {
309 if self.slice.len()
311 >= unsafe { self.slice.start.prefix() }
312 .capacity
313 .load(core::sync::atomic::Ordering::Relaxed)
314 {
315 return Err(value);
316 }
317 unsafe {
319 core::ptr::write(self.slice.end.as_ptr(), value);
320 self.slice.end = NonNull::new_unchecked(self.slice.end.as_ptr().add(1));
321 }
322 Ok(())
323 }
324 pub(crate) fn into_raw_components(self) -> (AllocSlice<T, Alloc>, usize, Alloc) {
325 let slice = self.slice;
326 let alloc = unsafe { core::ptr::read(&self.alloc) };
328 core::mem::forget(self);
329 let capacity = if core::mem::size_of::<T>() == 0 || slice.is_empty() {
330 0
331 } else {
332 unsafe {
334 slice
335 .start
336 .prefix()
337 .capacity
338 .load(core::sync::atomic::Ordering::Relaxed)
339 }
340 };
341 (slice, capacity, alloc)
342 }
343}
344impl<T, Alloc: IAlloc> core::ops::Deref for BoxedSlice<T, Alloc> {
345 type Target = [T];
346 fn deref(&self) -> &Self::Target {
347 self.as_slice()
348 }
349}
350
351impl<T, Alloc: IAlloc> core::ops::DerefMut for BoxedSlice<T, Alloc> {
352 fn deref_mut(&mut self) -> &mut Self::Target {
353 self.as_slice_mut()
354 }
355}
356impl<T: Eq, Alloc: IAlloc> Eq for BoxedSlice<T, Alloc> {}
357impl<T: PartialEq, Alloc: IAlloc> PartialEq for BoxedSlice<T, Alloc> {
358 fn eq(&self, other: &Self) -> bool {
359 self.as_slice() == other.as_slice()
360 }
361}
362impl<T: Ord, Alloc: IAlloc> Ord for BoxedSlice<T, Alloc> {
363 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
364 self.as_slice().cmp(other.as_slice())
365 }
366}
367impl<T: PartialOrd, Alloc: IAlloc> PartialOrd for BoxedSlice<T, Alloc> {
368 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
369 self.as_slice().partial_cmp(other.as_slice())
370 }
371}
372impl<T: core::hash::Hash, Alloc: IAlloc> core::hash::Hash for BoxedSlice<T, Alloc> {
373 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
374 self.as_slice().hash(state)
375 }
376}
377impl<T, Alloc: IAlloc> From<Vec<T, Alloc>> for BoxedSlice<T, Alloc> {
378 fn from(value: Vec<T, Alloc>) -> Self {
379 let (mut slice, capacity, alloc) = value.into_raw_components();
380 if capacity != 0 {
381 unsafe {
383 slice.start.prefix_mut().capacity = core::sync::atomic::AtomicUsize::new(capacity);
384 }
385 Self {
386 slice: AllocSlice {
387 start: slice.start,
388 end: slice.end,
389 },
390 alloc,
391 }
392 } else {
393 Self { slice, alloc }
394 }
395 }
396}
397impl<T, Alloc: IAlloc> From<BoxedSlice<T, Alloc>> for Vec<T, Alloc> {
398 fn from(value: BoxedSlice<T, Alloc>) -> Self {
399 let (slice, capacity, alloc) = value.into_raw_components();
400 if capacity != 0 {
401 Vec {
402 inner: VecInner {
403 start: slice.start,
404 end: slice.end,
405 capacity: ptr_add(slice.start.ptr, capacity),
406 alloc,
407 },
408 }
409 } else {
410 Vec {
411 inner: VecInner {
412 start: slice.start,
413 end: slice.end,
414 capacity: if core::mem::size_of::<T>() == 0 {
415 unsafe { core::mem::transmute::<usize, NonNull<T>>(usize::MAX) }
416 } else {
417 slice.start.ptr
418 },
419 alloc,
420 },
421 }
422 }
423 }
424}
425impl<T: Copy, Alloc: IAlloc + Default> From<&[T]> for BoxedSlice<T, Alloc> {
426 fn from(value: &[T]) -> Self {
427 Vec::from(value).into()
428 }
429}
430impl<T, Alloc: IAlloc + Default> FromIterator<T> for BoxedSlice<T, Alloc> {
431 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
432 Vec::from_iter(iter).into()
433 }
434}
435
436impl<T, Alloc: IAlloc> Drop for BoxedSlice<T, Alloc> {
437 fn drop(&mut self) {
438 unsafe { core::ptr::drop_in_place(self.as_slice_mut()) }
439 if core::mem::size_of::<T>() != 0 && !self.is_empty() {
440 unsafe { self.slice.start.free(&mut self.alloc) }
441 }
442 }
443}
444
445impl<T: Debug, Alloc: IAlloc> Debug for BoxedSlice<T, Alloc> {
446 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
447 self.as_slice().fmt(f)
448 }
449}
450impl<T: core::fmt::LowerHex, Alloc: IAlloc> core::fmt::LowerHex for BoxedSlice<T, Alloc> {
451 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
452 let mut first = true;
453 for item in self {
454 if !first {
455 f.write_str(":")?;
456 }
457 first = false;
458 core::fmt::LowerHex::fmt(item, f)?;
459 }
460 Ok(())
461 }
462}
463impl<T: core::fmt::UpperHex, Alloc: IAlloc> core::fmt::UpperHex for BoxedSlice<T, Alloc> {
464 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
465 let mut first = true;
466 for item in self {
467 if !first {
468 f.write_str(":")?;
469 }
470 first = false;
471 core::fmt::UpperHex::fmt(item, f)?;
472 }
473 Ok(())
474 }
475}
476impl<'a, T, Alloc: IAlloc> IntoIterator for &'a BoxedSlice<T, Alloc> {
477 type Item = &'a T;
478 type IntoIter = core::slice::Iter<'a, T>;
479 fn into_iter(self) -> Self::IntoIter {
480 self.as_slice().iter()
481 }
482}
483impl<'a, T, Alloc: IAlloc> IntoIterator for &'a mut BoxedSlice<T, Alloc> {
484 type Item = &'a mut T;
485 type IntoIter = core::slice::IterMut<'a, T>;
486 fn into_iter(self) -> Self::IntoIter {
487 self.as_slice_mut().iter_mut()
488 }
489}
490impl<T, Alloc: IAlloc> IntoIterator for BoxedSlice<T, Alloc> {
491 type Item = T;
492 type IntoIter = super::vec::IntoIter<T, Alloc>;
493 fn into_iter(self) -> Self::IntoIter {
494 let this: super::vec::Vec<T, Alloc> = self.into();
495 this.into_iter()
496 }
497}
498pub use super::string::BoxedStr;
499
500#[cfg(feature = "serde")]
501mod serde_impl {
502 use super::*;
503 use crate::alloc::IAlloc;
504 use serde::{Deserialize, Serialize};
505 impl<T: Serialize, Alloc: IAlloc> Serialize for BoxedSlice<T, Alloc> {
506 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
507 where
508 S: serde::Serializer,
509 {
510 let slice: &[T] = self;
511 slice.serialize(serializer)
512 }
513 }
514 impl<'a, T: Deserialize<'a>, Alloc: IAlloc + Default> Deserialize<'a> for BoxedSlice<T, Alloc> {
515 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
516 where
517 D: serde::Deserializer<'a>,
518 {
519 crate::alloc::vec::Vec::deserialize(deserializer).map(Into::into)
520 }
521 }
522 impl<Alloc: IAlloc> Serialize for BoxedStr<Alloc> {
523 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
524 where
525 S: serde::Serializer,
526 {
527 let slice: &str = self;
528 slice.serialize(serializer)
529 }
530 }
531 impl<'a, Alloc: IAlloc + Default> Deserialize<'a> for BoxedStr<Alloc> {
532 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
533 where
534 D: serde::Deserializer<'a>,
535 {
536 crate::alloc::string::String::deserialize(deserializer).map(Into::into)
537 }
538 }
539}