1use crate::allocator::{AllocError, Allocator, DefaultAllocator};
8use core::mem::MaybeUninit;
9use core::ops::{Deref, DerefMut};
10use core::pin::Pin;
11use core::ptr::NonNull;
12use pin_init::PinInit;
13use zerocopy::FromZeros;
14
15fn dangling_slice<T>(len: usize) -> NonNull<[MaybeUninit<T>]> {
17 let dangling = NonNull::<T>::dangling();
18 NonNull::slice_from_raw_parts(dangling.cast::<MaybeUninit<T>>(), len)
19}
20
21fn allocate_slice<T, A: Allocator>(
23 allocator: &A,
24 len: usize,
25) -> Result<NonNull<[MaybeUninit<T>]>, AllocError> {
26 let layout = core::alloc::Layout::array::<T>(len).map_err(|_| AllocError)?;
27 if layout.size() == 0 {
28 return Ok(dangling_slice::<T>(len));
29 }
30 let ptr = allocator.allocate(layout)?;
31 let casted_thin = ptr.cast::<MaybeUninit<T>>();
32 Ok(NonNull::slice_from_raw_parts(casted_thin, len))
33}
34
35fn allocate_zeroed_slice<T, A: Allocator>(
37 allocator: &A,
38 len: usize,
39) -> Result<NonNull<[MaybeUninit<T>]>, AllocError> {
40 let layout = core::alloc::Layout::array::<T>(len).map_err(|_| AllocError)?;
41 if layout.size() == 0 {
42 return Ok(dangling_slice::<T>(len));
43 }
44 let ptr = allocator.allocate_zeroed(layout)?;
45 let casted_thin = ptr.cast::<MaybeUninit<T>>();
46 Ok(NonNull::slice_from_raw_parts(casted_thin, len))
47}
48
49unsafe fn deallocate_slice<T, A: Allocator>(allocator: &A, ptr: NonNull<[MaybeUninit<T>]>) {
56 let len = ptr.len();
57 unsafe {
59 let layout = core::alloc::Layout::array::<T>(len).unwrap_unchecked();
60 if layout.size() == 0 {
61 return;
62 }
63 allocator.deallocate(ptr.cast::<u8>(), layout);
64 }
65}
66
67unsafe fn grow_slice<T, A: Allocator>(
74 allocator: &A,
75 ptr: NonNull<[MaybeUninit<T>]>,
76 new_len: usize,
77) -> Result<NonNull<[MaybeUninit<T>]>, AllocError> {
78 let old_len = ptr.len();
79 assert!(new_len > old_len);
80
81 let old_layout = core::alloc::Layout::array::<T>(old_len).map_err(|_| AllocError)?;
82 let new_layout = core::alloc::Layout::array::<T>(new_len).map_err(|_| AllocError)?;
83
84 if old_layout.size() == 0 {
85 return allocate_slice(allocator, new_len);
86 }
87
88 let new_ptr = unsafe { allocator.grow(ptr.cast::<u8>(), old_layout, new_layout)? };
90 Ok(NonNull::slice_from_raw_parts(new_ptr.cast::<MaybeUninit<T>>(), new_len))
91}
92
93unsafe fn shrink_slice<T, A: Allocator>(
100 allocator: &A,
101 ptr: NonNull<[MaybeUninit<T>]>,
102 new_len: usize,
103) -> Result<NonNull<[MaybeUninit<T>]>, AllocError> {
104 let old_len = ptr.len();
105 assert!(new_len < old_len);
106
107 let old_layout = core::alloc::Layout::array::<T>(old_len).map_err(|_| AllocError)?;
108 let new_layout = core::alloc::Layout::array::<T>(new_len).map_err(|_| AllocError)?;
109
110 if new_layout.size() == 0 {
111 unsafe {
113 deallocate_slice::<T, A>(allocator, ptr);
114 }
115 return Ok(dangling_slice::<T>(new_len));
116 }
117
118 let new_ptr = unsafe { allocator.shrink(ptr.cast::<u8>(), old_layout, new_layout)? };
120 Ok(NonNull::slice_from_raw_parts(new_ptr.cast::<MaybeUninit<T>>(), new_len))
121}
122
123pub struct Box<T: ?Sized, A: Allocator = DefaultAllocator> {
125 ptr: NonNull<T>,
137 allocator: A,
138}
139
140impl<T: ?Sized, A: Allocator> Box<T, A> {
141 pub const unsafe fn from_raw_in(ptr: *mut T, allocator: A) -> Self {
153 unsafe { Self::from_non_null_in(NonNull::new_unchecked(ptr), allocator) }
156 }
157
158 pub const unsafe fn from_non_null_in(ptr: NonNull<T>, allocator: A) -> Self {
167 Self { ptr, allocator }
168 }
169
170 pub fn as_ptr(this: &Self) -> *mut T {
172 this.ptr.as_ptr()
173 }
174
175 pub fn into_raw_with_allocator(this: Self) -> (*mut T, A) {
189 let me = core::mem::ManuallyDrop::new(this);
190 let ptr = me.ptr.as_ptr();
191 let allocator = unsafe { core::ptr::read(&me.allocator) };
194 (ptr, allocator)
195 }
196}
197
198impl<T: ?Sized> Box<T, DefaultAllocator> {
199 pub const unsafe fn from_raw(ptr: *mut T) -> Self {
208 unsafe { Self::from_raw_in(ptr, DefaultAllocator) }
209 }
210
211 pub const unsafe fn from_non_null(ptr: NonNull<T>) -> Self {
220 unsafe { Self::from_non_null_in(ptr, DefaultAllocator) }
221 }
222
223 pub fn into_raw(this: Self) -> *mut T {
227 let (ptr, _) = Box::into_raw_with_allocator(this);
228 ptr
229 }
230}
231
232impl<T, A: Allocator> Box<[T], A> {
233 pub const fn empty_slice_in(allocator: A) -> Self {
237 unsafe { Self::from_non_null_in(NonNull::from_ref(&[]), allocator) }
240 }
241
242 pub fn try_new_uninit_slice_in(
244 len: usize,
245 allocator: A,
246 ) -> Result<Box<[MaybeUninit<T>], A>, AllocError> {
247 let fat_ptr = allocate_slice::<T, A>(&allocator, len)?;
248 Ok(unsafe { Box::from_non_null_in(fat_ptr, allocator) })
250 }
251
252 pub fn try_new_zeroed_uninit_slice_in(
254 len: usize,
255 allocator: A,
256 ) -> Result<Box<[MaybeUninit<T>], A>, AllocError> {
257 let fat_ptr = allocate_zeroed_slice::<T, A>(&allocator, len)?;
258 Ok(unsafe { Box::from_non_null_in(fat_ptr, allocator) })
260 }
261}
262
263impl<T> Box<[T], DefaultAllocator> {
264 pub const fn empty_slice() -> Self {
265 Self::empty_slice_in(DefaultAllocator)
266 }
267
268 pub fn try_new_uninit_slice(
269 len: usize,
270 ) -> Result<Box<[MaybeUninit<T>], DefaultAllocator>, AllocError> {
271 Self::try_new_uninit_slice_in(len, DefaultAllocator)
272 }
273
274 pub fn try_new_zeroed_uninit_slice(
276 len: usize,
277 ) -> Result<Box<[MaybeUninit<T>], DefaultAllocator>, AllocError> {
278 Self::try_new_zeroed_uninit_slice_in(len, DefaultAllocator)
279 }
280}
281
282impl<T: FromZeros, A: Allocator> Box<[T], A> {
283 pub fn try_new_zeroed_slice_in(len: usize, allocator: A) -> Result<Self, AllocError> {
285 let fat_ptr = allocate_zeroed_slice::<T, A>(&allocator, len)?;
286 let ptr = fat_ptr.as_ptr() as *mut [T];
289 Ok(unsafe { Self::from_non_null_in(NonNull::new_unchecked(ptr), allocator) })
291 }
292}
293
294impl<T: FromZeros> Box<[T], DefaultAllocator> {
295 pub fn try_new_zeroed_slice(len: usize) -> Result<Self, AllocError> {
297 Self::try_new_zeroed_slice_in(len, DefaultAllocator)
298 }
299}
300
301impl<T, A: Allocator> Box<[MaybeUninit<T>], A> {
302 pub unsafe fn assume_init(self) -> Box<[T], A> {
308 let (ptr, allocator) = Box::into_raw_with_allocator(self);
309 let ptr = ptr as *mut [T];
310 unsafe { Box::from_raw_in(ptr, allocator) }
312 }
313
314 pub fn try_grow(this: &mut Self, new_len: usize) -> Result<(), AllocError> {
317 this.ptr = unsafe { grow_slice::<T, A>(&this.allocator, this.ptr, new_len)? };
319 Ok(())
320 }
321
322 pub unsafe fn try_shrink(this: &mut Self, new_len: usize) -> Result<(), AllocError> {
332 this.ptr = unsafe { shrink_slice::<T, A>(&this.allocator, this.ptr, new_len)? };
334 Ok(())
335 }
336}
337
338pub trait PinInitError {
341 type Error;
343
344 fn from_alloc_error(err: AllocError) -> Self::Error;
346
347 fn into_error(self) -> Self::Error;
349}
350
351impl PinInitError for core::convert::Infallible {
352 type Error = AllocError;
353
354 fn from_alloc_error(err: AllocError) -> Self::Error {
355 err
356 }
357
358 fn into_error(self) -> Self::Error {
359 match self {}
360 }
361}
362
363impl PinInitError for AllocError {
364 type Error = AllocError;
365
366 fn from_alloc_error(err: AllocError) -> Self::Error {
367 err
368 }
369
370 fn into_error(self) -> Self::Error {
371 self
372 }
373}
374
375impl PinInitError for zx_status::Status {
376 type Error = zx_status::Status;
377
378 fn from_alloc_error(err: AllocError) -> Self::Error {
379 err.into()
380 }
381
382 fn into_error(self) -> Self::Error {
383 self
384 }
385}
386
387impl<T, A: Allocator> Box<T, A> {
388 const fn new_zst_in(allocator: A) -> Self {
394 assert!(core::mem::size_of::<T>() == 0);
395 Self { ptr: NonNull::<T>::dangling(), allocator }
397 }
398
399 pub fn try_new_in(value: T, allocator: A) -> Result<Self, AllocError> {
401 let mut b = Self::try_new_uninit_in(allocator)?;
402 b.write(value);
403 Ok(unsafe { b.assume_init() })
404 }
405
406 pub fn try_pin_init_in<E: PinInitError>(
408 init: impl PinInit<T, E>,
409 allocator: A,
410 ) -> Result<Pin<Self>, E::Error> {
411 let mut b = Self::try_new_uninit_in(allocator).map_err(E::from_alloc_error)?;
412 unsafe { init.__pinned_init(b.as_mut_ptr()).map_err(E::into_error)? };
416 let b = unsafe { b.assume_init() };
418 Ok(unsafe { Pin::new_unchecked(b) })
420 }
421
422 pub fn try_new_uninit_in(allocator: A) -> Result<Box<MaybeUninit<T>, A>, AllocError> {
424 if core::mem::size_of::<T>() == 0 {
425 return Ok(Box::<MaybeUninit<T>, A>::new_zst_in(allocator));
426 }
427 let layout = core::alloc::Layout::new::<T>();
428 let ptr = allocator.allocate(layout)?.cast::<MaybeUninit<T>>();
429 Ok(unsafe { Box::from_non_null_in(ptr, allocator) })
431 }
432
433 pub fn try_new_zeroed_in(allocator: A) -> Result<Box<MaybeUninit<T>, A>, AllocError> {
435 if core::mem::size_of::<T>() == 0 {
436 return Ok(Box::<MaybeUninit<T>, A>::new_zst_in(allocator));
437 }
438 let layout = core::alloc::Layout::new::<T>();
439 let ptr = allocator.allocate_zeroed(layout)?.cast::<MaybeUninit<T>>();
440 Ok(unsafe { Box::from_non_null_in(ptr, allocator) })
442 }
443}
444
445impl<T> Box<T, DefaultAllocator> {
446 pub fn try_new(value: T) -> Result<Self, AllocError> {
447 Self::try_new_in(value, DefaultAllocator)
448 }
449
450 pub fn try_pin_init<E: PinInitError>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E::Error> {
451 Self::try_pin_init_in(init, DefaultAllocator)
452 }
453
454 pub fn try_new_uninit() -> Result<Box<MaybeUninit<T>>, AllocError> {
455 Self::try_new_uninit_in(DefaultAllocator)
456 }
457
458 pub fn try_new_zeroed() -> Result<Box<MaybeUninit<T>>, AllocError> {
459 Self::try_new_zeroed_in(DefaultAllocator)
460 }
461}
462
463impl<T, A: Allocator> Box<MaybeUninit<T>, A> {
464 pub unsafe fn assume_init(self) -> Box<T, A> {
470 let (ptr, allocator) = Box::into_raw_with_allocator(self);
471 unsafe { Box::from_raw_in(ptr as *mut T, allocator) }
473 }
474}
475
476impl<T> Default for Box<[T]> {
477 fn default() -> Self {
478 Self::empty_slice()
479 }
480}
481
482impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
483 type Target = T;
484 fn deref(&self) -> &Self::Target {
485 unsafe { self.ptr.as_ref() }
487 }
488}
489
490impl<T: ?Sized, A: Allocator> DerefMut for Box<T, A> {
491 fn deref_mut(&mut self) -> &mut Self::Target {
492 unsafe { self.ptr.as_mut() }
494 }
495}
496
497impl<T: ?Sized, A: Allocator> Drop for Box<T, A> {
498 fn drop(&mut self) {
499 unsafe {
501 let value = self.ptr.as_mut();
502 let layout = core::alloc::Layout::for_value(value);
503 core::ptr::drop_in_place(value);
504 if layout.size() > 0 {
505 self.allocator.deallocate(self.ptr.cast::<u8>(), layout);
506 }
507 }
508 }
509}
510
511#[cfg(test)]
512mod tests {
513 use super::*;
514 use core::alloc::Layout;
515
516 #[test]
517 fn test_box_default_slice() {
518 let b = Box::<[u32]>::default();
519 assert_eq!(b.len(), 0);
520 }
521
522 #[test]
523 fn test_box_empty_slice() {
524 let b = Box::<[u32]>::empty_slice();
525 assert_eq!(b.len(), 0);
526 assert!(Box::as_ptr(&b) as *mut u8 == NonNull::<u32>::dangling().as_ptr() as *mut u8);
527 }
528
529 #[test]
530 fn test_box_try_new() {
531 let b = Box::<u32>::try_new(42).unwrap();
532 assert_eq!(*b, 42);
533 }
534
535 #[test]
536 fn test_box() {
537 let b = Box::<[u32]>::try_new_uninit_slice(10).unwrap();
538 assert_eq!(b.len(), 10);
539 }
540
541 #[test]
542 fn test_box_deref() {
543 let mut b = Box::<[u32]>::try_new_uninit_slice(1).unwrap();
544 b[0].write(0);
545 let mut b = unsafe { b.assume_init() };
547 assert_eq!(b[0], 0);
548 b[0] = 42;
549 assert_eq!(b[0], 42);
550 }
551
552 #[test]
553 fn test_box_as_ptr() {
554 let b = Box::<[u32]>::try_new_uninit_slice(10).unwrap();
555 let ptr = Box::as_ptr(&b);
556 assert!(!ptr.is_null());
557 }
558
559 #[test]
560 fn test_box_from_raw() {
561 let mut b = Box::<[u32]>::try_new_uninit_slice(10).unwrap();
562 b.fill(MaybeUninit::new(0));
563 let raw_ptr = Box::into_raw(b);
564 let fat_ptr = raw_ptr as *mut [u32];
565
566 let b2: Box<[u32]> = unsafe { Box::from_raw(fat_ptr) };
571 assert_eq!(b2.len(), 10);
572 assert_eq!(*b2, [0; 10]);
573 }
575
576 struct DropObserver<'a> {
577 dropped: &'a core::cell::Cell<bool>,
578 }
579
580 impl<'a> Drop for DropObserver<'a> {
581 fn drop(&mut self) {
582 self.dropped.set(true);
583 }
584 }
585
586 #[test]
587 fn test_box_drops_content() {
588 use core::cell::Cell;
589 let dropped = Cell::new(false);
590 {
591 let observer = DropObserver { dropped: &dropped };
592 let _b: Box<DropObserver<'_>> = Box::try_new(observer).unwrap();
593 assert_eq!(dropped.get(), false);
594 } assert_eq!(dropped.get(), true);
596 }
597
598 #[test]
599 #[should_panic]
600 fn test_box_slice_out_of_bounds() {
601 let b = Box::<[u32]>::try_new_uninit_slice(5).unwrap();
602 let _ = b[5]; }
604
605 #[derive(Clone, Default)]
606 struct AlwaysFailingAllocator;
607
608 impl Allocator for AlwaysFailingAllocator {
609 fn allocate(&self, _layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
610 Err(AllocError)
611 }
612
613 unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
614 panic!("Deallocate called on AlwaysFailingAllocator");
615 }
616
617 unsafe fn grow(
618 &self,
619 _ptr: NonNull<u8>,
620 _old_layout: Layout,
621 _new_layout: Layout,
622 ) -> Result<NonNull<[u8]>, AllocError> {
623 Err(AllocError)
624 }
625
626 unsafe fn shrink(
627 &self,
628 _ptr: NonNull<u8>,
629 _old_layout: Layout,
630 _new_layout: Layout,
631 ) -> Result<NonNull<[u8]>, AllocError> {
632 Err(AllocError)
633 }
634
635 fn allocate_zeroed(&self, _layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
636 Err(AllocError)
637 }
638 }
639
640 #[test]
641 fn test_box_try_new_failing() {
642 let b =
643 Box::<u32, AlwaysFailingAllocator>::try_new_in(42, AlwaysFailingAllocator::default());
644 assert!(b.is_err());
645 }
646
647 #[test]
648 fn test_box_try_new_slice_failing() {
649 let b = Box::<[u32], AlwaysFailingAllocator>::try_new_uninit_slice_in(
650 10,
651 AlwaysFailingAllocator::default(),
652 );
653 assert!(b.is_err());
654 }
655
656 #[test]
657 fn test_box_try_new_zeroed() {
658 let b = Box::<u32>::try_new_zeroed().unwrap();
659 let b = unsafe { b.assume_init() };
660 assert_eq!(*b, 0);
661 }
662
663 #[test]
664 fn test_box_try_new_zeroed_slice() {
665 let b = Box::<[u32]>::try_new_zeroed_slice(3).unwrap();
666 assert_eq!(*b, [0, 0, 0]);
667 }
668
669 #[test]
670 fn test_box_try_grow() {
671 let mut b = Box::<[u32]>::try_new_uninit_slice(2).unwrap();
672 b[0].write(10);
673 b[1].write(20);
674
675 Box::try_grow(&mut b, 5).unwrap();
676 assert_eq!(b.len(), 5);
677 assert_eq!(unsafe { b[0].assume_init() }, 10);
678 assert_eq!(unsafe { b[1].assume_init() }, 20);
679 }
680
681 #[test]
682 fn test_box_try_shrink() {
683 let mut b = Box::<[u32]>::try_new_uninit_slice(5).unwrap();
684 b[0].write(10);
685 b[1].write(20);
686
687 unsafe {
688 Box::try_shrink(&mut b, 2).unwrap();
689 }
690 assert_eq!(b.len(), 2);
691 assert_eq!(unsafe { b[0].assume_init() }, 10);
692 assert_eq!(unsafe { b[1].assume_init() }, 20);
693 }
694
695 #[test]
696 fn test_box_from_non_null() {
697 use core::alloc::Layout;
698 let layout = Layout::new::<u32>();
699 let ptr = DefaultAllocator::default().allocate(layout).unwrap();
700 let casted = ptr.cast::<u32>();
701 unsafe {
702 casted.as_ptr().write(42);
703 }
704 let b: Box<u32, DefaultAllocator> = unsafe { Box::from_non_null(casted) };
705 assert_eq!(*b, 42);
706 }
707
708 #[test]
709 fn test_box_into_raw() {
710 let b = Box::try_new(42u32).unwrap();
711 let ptr = Box::into_raw(b);
712 assert_eq!(unsafe { *ptr }, 42);
713 unsafe {
714 *ptr = 100;
715 }
716 assert_eq!(unsafe { *ptr }, 100);
717
718 let b = unsafe { Box::from_raw(ptr) };
720 assert_eq!(*b, 100);
721 }
722
723 #[test]
724 fn test_box_into_raw_with_allocator() {
725 let b = Box::try_new(42u32).unwrap();
726 let (ptr, allocator) = Box::into_raw_with_allocator(b);
727 assert_eq!(unsafe { *ptr }, 42);
728
729 let b = unsafe { Box::from_raw_in(ptr, allocator) };
731 assert_eq!(*b, 42);
732 }
733
734 #[test]
735 fn test_box_assume_init_range() {
736 let mut b = Box::<[u32]>::try_new_uninit_slice(5).unwrap();
737 unsafe {
738 b[1].as_mut_ptr().write(10);
739 b[2].as_mut_ptr().write(20);
740 }
741
742 let slice = unsafe { b[1..3].assume_init_ref() };
743 assert_eq!(slice, [10, 20]);
744
745 let slice_mut = unsafe { b[1..3].assume_init_mut() };
746 slice_mut[0] = 30;
747 assert_eq!(unsafe { b[1].assume_init() }, 30);
748 }
749
750 #[derive(Clone)]
751 struct TrackingAllocator {
752 allocated: alloc::sync::Arc<core::cell::RefCell<alloc::collections::BTreeSet<usize>>>,
753 }
754
755 impl TrackingAllocator {
756 fn new() -> Self {
757 Self {
758 allocated: alloc::sync::Arc::new(core::cell::RefCell::new(
759 alloc::collections::BTreeSet::new(),
760 )),
761 }
762 }
763 }
764
765 impl Allocator for TrackingAllocator {
766 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
767 let ptr = DefaultAllocator::default().allocate(layout)?;
768 let addr = ptr.as_ptr() as *mut u8 as usize;
769 self.allocated.borrow_mut().insert(addr);
770 Ok(ptr)
771 }
772
773 fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
774 let ptr = DefaultAllocator::default().allocate_zeroed(layout)?;
775 let addr = ptr.as_ptr() as *mut u8 as usize;
776 self.allocated.borrow_mut().insert(addr);
777 Ok(ptr)
778 }
779
780 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
781 let addr = ptr.as_ptr() as usize;
782 let mut allocated = self.allocated.borrow_mut();
783 if !allocated.remove(&addr) {
784 panic!("Deallocate called on address not produced by allocator: {:p}", ptr);
785 }
786 unsafe {
788 DefaultAllocator::default().deallocate(ptr, layout);
789 }
790 }
791
792 unsafe fn grow(
793 &self,
794 ptr: NonNull<u8>,
795 old_layout: Layout,
796 new_layout: Layout,
797 ) -> Result<NonNull<[u8]>, AllocError> {
798 let addr = ptr.as_ptr() as usize;
799 let mut allocated = self.allocated.borrow_mut();
800 if !allocated.remove(&addr) {
801 panic!("Grow called on address not produced by allocator: {:p}", ptr);
802 }
803 let new_ptr = unsafe { DefaultAllocator::default().grow(ptr, old_layout, new_layout)? };
805 let new_addr = new_ptr.as_ptr() as *mut u8 as usize;
806 allocated.insert(new_addr);
807 Ok(new_ptr)
808 }
809
810 unsafe fn shrink(
811 &self,
812 ptr: NonNull<u8>,
813 old_layout: Layout,
814 new_layout: Layout,
815 ) -> Result<NonNull<[u8]>, AllocError> {
816 let addr = ptr.as_ptr() as usize;
817 let mut allocated = self.allocated.borrow_mut();
818 if !allocated.remove(&addr) {
819 panic!("Shrink called on address not produced by allocator: {:p}", ptr);
820 }
821 let new_ptr =
823 unsafe { DefaultAllocator::default().shrink(ptr, old_layout, new_layout)? };
824 let new_addr = new_ptr.as_ptr() as *mut u8 as usize;
825 allocated.insert(new_addr);
826 Ok(new_ptr)
827 }
828 }
829
830 #[test]
831 fn test_empty_slice_and_zst_allocator_interactions() {
832 let alloc = TrackingAllocator::new();
833
834 {
836 let b = Box::<[u32], TrackingAllocator>::empty_slice_in(alloc.clone());
837 assert_eq!(b.len(), 0);
838 }
840
841 struct Zst;
843 {
844 let _b = Box::<Zst, TrackingAllocator>::try_new_in(Zst, alloc.clone()).unwrap();
845 }
847
848 {
850 let mut b = Box::<[core::mem::MaybeUninit<u32>], TrackingAllocator>::empty_slice_in(
851 alloc.clone(),
852 );
853 Box::try_grow(&mut b, 5).unwrap();
854 let addr = Box::as_ptr(&b) as *mut u8 as usize;
856 assert!(alloc.allocated.borrow().contains(&addr));
857 } {
861 let mut b =
862 Box::<[u32], TrackingAllocator>::try_new_uninit_slice_in(5, alloc.clone()).unwrap();
863 let addr = Box::as_ptr(&b) as *mut u8 as usize;
864 assert!(alloc.allocated.borrow().contains(&addr));
865
866 unsafe {
867 Box::try_shrink(&mut b, 0).unwrap();
868 }
869 assert_eq!(b.len(), 0);
870 assert!(!alloc.allocated.borrow().contains(&addr));
872 }
873 }
874
875 #[test]
876 fn test_try_new_zeroed_uninit_slice() {
877 let b = Box::<[u32]>::try_new_zeroed_uninit_slice(4).unwrap();
879 assert_eq!(b.len(), 4);
880 for x in b.as_ref() {
881 assert_eq!(unsafe { x.assume_init() }, 0);
882 }
883
884 struct NotZeroable {
886 _a: u32,
887 _b: u32,
888 }
889 let b = Box::<[NotZeroable]>::try_new_zeroed_uninit_slice(4).unwrap();
890 assert_eq!(b.len(), 4);
891 }
892
893 #[pin_init::pin_data(PinnedDrop)]
894 struct PinnedTest<'a> {
895 self_ptr: *const PinnedTest<'a>,
896 dropped: &'a core::cell::Cell<bool>,
897 #[pin]
898 _pin: core::marker::PhantomPinned,
899 }
900
901 #[pin_init::pinned_drop]
902 impl PinnedDrop for PinnedTest<'_> {
903 fn drop(self: Pin<&mut Self>) {
904 assert!(core::ptr::eq(self.self_ptr, &*self));
905 self.dropped.set(true);
906 }
907 }
908
909 impl<'a> PinnedTest<'a> {
910 fn new(dropped: &'a core::cell::Cell<bool>) -> impl PinInit<Self> {
911 pin_init::pin_init!(&this in Self {
912 self_ptr: this.as_ptr(),
913 dropped,
914 _pin: core::marker::PhantomPinned,
915 })
916 }
917
918 fn new_fallible(
919 dropped: &'a core::cell::Cell<bool>,
920 status: Result<(), zx_status::Status>,
921 ) -> impl PinInit<Self, zx_status::Status> {
922 pin_init::pin_init!(&this in Self {
923 self_ptr: {
924 status?;
925 this.as_ptr()
926 },
927 dropped,
928 _pin: core::marker::PhantomPinned,
929 } ? zx_status::Status)
930 }
931 }
932
933 #[test]
934 fn test_box_try_pin_init() {
935 let dropped = core::cell::Cell::new(false);
936 {
937 let b = Box::try_pin_init(PinnedTest::new(&dropped)).unwrap();
938 assert!(core::ptr::eq(b.self_ptr, &*b));
939 assert!(!dropped.get());
940 }
941 assert!(dropped.get());
942 }
943
944 #[test]
945 fn test_box_try_pin_init_failing() {
946 let dropped = core::cell::Cell::new(false);
947 let b = Box::<PinnedTest<'_>, AlwaysFailingAllocator>::try_pin_init_in(
948 PinnedTest::new(&dropped),
949 AlwaysFailingAllocator,
950 );
951 assert!(b.is_err());
952 assert!(!dropped.get());
953
954 let alloc = TrackingAllocator::new();
955 let b_init_err = Box::<PinnedTest<'_>, TrackingAllocator>::try_pin_init_in(
956 PinnedTest::new_fallible(&dropped, Err(zx_status::Status::INVALID_ARGS)),
957 alloc.clone(),
958 );
959 assert_eq!(b_init_err.err(), Some(zx_status::Status::INVALID_ARGS));
960 assert!(!dropped.get());
961 assert!(alloc.allocated.borrow().is_empty());
962
963 let b_alloc_err = Box::<PinnedTest<'_>, AlwaysFailingAllocator>::try_pin_init_in(
964 PinnedTest::new_fallible(&dropped, Ok(())),
965 AlwaysFailingAllocator,
966 );
967 assert_eq!(b_alloc_err.err(), Some(zx_status::Status::NO_MEMORY));
968 assert!(!dropped.get());
969 }
970}