1use core::convert::Infallible;
8use core::mem::MaybeUninit;
9use core::ops::{Deref, DerefMut};
10use core::pin::Pin;
11use core::ptr::slice_from_raw_parts_mut;
12use kalloc::{AllocError, Allocator, Box, DefaultAllocator};
13use pin_init::PinInit;
14use zerocopy::FromZeros;
15
16pub struct Array<T, A: Allocator = DefaultAllocator> {
19 buf: Box<[T], A>,
20}
21
22zr::static_assert!(core::mem::size_of::<Array<u32>>() == 16);
23zr::static_assert!(core::mem::align_of::<Array<u32>>() == 8);
24
25impl<T, A: Allocator> Array<T, A> {
26 pub const fn new_in(allocator: A) -> Self {
28 Self { buf: Box::empty_slice_in(allocator) }
29 }
30
31 pub fn from_box(buf: Box<[T], A>) -> Self {
33 Self { buf }
34 }
35
36 pub fn try_new_in(len: usize, allocator: A) -> Result<Self, AllocError>
38 where
39 T: Default,
40 {
41 let mut b = Box::<[T], A>::try_new_uninit_slice_in(len, allocator)?;
42 for i in 0..len {
43 b[i].write(T::default());
44 }
45 Ok(Self { buf: unsafe { b.assume_init() } })
47 }
48
49 pub fn try_new_pin_init_in<I, F>(
55 len: usize,
56 mut init: F,
57 allocator: A,
58 ) -> Result<Pin<Self>, AllocError>
59 where
60 F: FnMut() -> I,
61 I: PinInit<T, Infallible>,
62 {
63 let mut b = Box::<[T], A>::try_new_uninit_slice_in(len, allocator)?;
64
65 struct InitGuard<'a, T> {
68 slots: &'a mut [MaybeUninit<T>],
69 initialized: usize,
70 }
71
72 impl<T> Drop for InitGuard<'_, T> {
73 fn drop(&mut self) {
74 for slot in &mut self.slots[..self.initialized] {
75 unsafe { slot.assume_init_drop() };
77 }
78 }
79 }
80
81 let mut guard = InitGuard { slots: &mut b, initialized: 0 };
82 while guard.initialized < len {
83 let slot = guard.slots[guard.initialized].as_mut_ptr();
84 match unsafe { init().__pinned_init(slot) } {
89 Ok(()) => guard.initialized += 1,
90 Err(never) => match never {},
91 }
92 }
93 core::mem::forget(guard);
94
95 Ok(Self { buf: unsafe { b.assume_init() } }.into_pin())
97 }
98
99 pub const fn into_pin(self) -> Pin<Self> {
104 unsafe { Pin::new_unchecked(self) }
110 }
111
112 pub fn try_new_uninit_slice_in(
114 len: usize,
115 allocator: A,
116 ) -> Result<Array<MaybeUninit<T>, A>, AllocError> {
117 Ok(Array { buf: Box::<[T], A>::try_new_uninit_slice_in(len, allocator)? })
118 }
119
120 pub fn into_raw_with_allocator(self) -> (*mut [T], A) {
124 Box::into_raw_with_allocator(self.buf)
125 }
126
127 pub fn into_raw_parts_with_allocator(self) -> (*mut T, usize, A) {
132 let (slice_ptr, allocator) = self.into_raw_with_allocator();
133 (slice_ptr as *mut T, slice_ptr.len(), allocator)
134 }
135
136 pub unsafe fn from_raw_in(ptr: *mut [T], allocator: A) -> Self {
143 Self { buf: unsafe { Box::from_raw_in(ptr, allocator) } }
144 }
145
146 pub unsafe fn from_raw_parts_in(ptr: *mut T, len: usize, allocator: A) -> Self {
155 let slice_ptr = slice_from_raw_parts_mut(ptr, len);
156 unsafe { Self::from_raw_in(slice_ptr, allocator) }
157 }
158
159 pub fn len(&self) -> usize {
161 self.buf.len()
162 }
163
164 pub fn is_empty(&self) -> bool {
166 self.buf.is_empty()
167 }
168
169 pub fn into_box(self) -> Box<[T], A> {
171 self.buf
172 }
173}
174
175impl<T: FromZeros, A: Allocator> Array<T, A> {
176 pub fn try_new_zeroed_slice_in(len: usize, allocator: A) -> Result<Self, AllocError> {
178 Ok(Self { buf: Box::<[T], A>::try_new_zeroed_slice_in(len, allocator)? })
179 }
180}
181
182impl<T: FromZeros> Array<T, DefaultAllocator> {
183 pub fn try_new_zeroed_slice(len: usize) -> Result<Self, AllocError> {
185 Self::try_new_zeroed_slice_in(len, DefaultAllocator)
186 }
187}
188
189impl<T> Array<T, DefaultAllocator> {
190 pub const fn new() -> Self {
192 Self { buf: Box::empty_slice() }
193 }
194
195 pub fn try_new(len: usize) -> Result<Self, AllocError>
197 where
198 T: Default,
199 {
200 Self::try_new_in(len, DefaultAllocator)
201 }
202
203 pub fn try_new_pin_init<I, F>(len: usize, init: F) -> Result<Pin<Self>, AllocError>
227 where
228 F: FnMut() -> I,
229 I: PinInit<T, Infallible>,
230 {
231 Self::try_new_pin_init_in(len, init, DefaultAllocator)
232 }
233
234 pub fn try_new_uninit_slice(
236 len: usize,
237 ) -> Result<Array<MaybeUninit<T>, DefaultAllocator>, AllocError> {
238 Self::try_new_uninit_slice_in(len, DefaultAllocator)
239 }
240
241 pub fn into_raw(self) -> *mut [T] {
245 let (ptr, _) = self.into_raw_with_allocator();
246 ptr
247 }
248
249 pub fn into_raw_parts(self) -> (*mut T, usize) {
254 let (ptr, len, _) = self.into_raw_parts_with_allocator();
255 (ptr, len)
256 }
257
258 pub unsafe fn from_raw(ptr: *mut [T]) -> Self {
265 unsafe { Self::from_raw_in(ptr, DefaultAllocator) }
266 }
267
268 pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self {
277 unsafe { Self::from_raw_parts_in(ptr, len, DefaultAllocator) }
278 }
279}
280
281impl<T, A: Allocator> Array<MaybeUninit<T>, A> {
282 pub unsafe fn assume_init(self) -> Array<T, A> {
288 Array { buf: unsafe { self.buf.assume_init() } }
289 }
290}
291
292impl<T, A: Allocator> Deref for Array<T, A> {
293 type Target = [T];
294
295 fn deref(&self) -> &Self::Target {
296 &self.buf
297 }
298}
299
300impl<T, A: Allocator> DerefMut for Array<T, A> {
301 fn deref_mut(&mut self) -> &mut Self::Target {
302 &mut self.buf
303 }
304}
305
306impl<T> Default for Array<T, DefaultAllocator> {
307 fn default() -> Self {
308 Self::new()
309 }
310}
311
312#[cfg(test)]
313mod tests {
314 use super::*;
315 use core::cell::Cell;
316 use core::ptr::NonNull;
317
318 #[derive(Debug, PartialEq, Eq)]
319 struct TestState {
320 live_obj_count: Cell<usize>,
321 ctor_count: Cell<usize>,
322 dtor_count: Cell<usize>,
323 alloc_count: Cell<usize>,
324 fail_threshold: Cell<usize>,
325 }
326
327 impl Default for TestState {
328 fn default() -> Self {
329 Self {
330 live_obj_count: Cell::new(0),
331 ctor_count: Cell::new(0),
332 dtor_count: Cell::new(0),
333 alloc_count: Cell::new(0),
334 fail_threshold: Cell::new(usize::MAX),
335 }
336 }
337 }
338
339 #[derive(Clone)]
340 struct TestAllocator<'a> {
341 state: &'a TestState,
342 }
343
344 impl<'a> kalloc::Allocator for TestAllocator<'a> {
345 fn allocate(&self, layout: core::alloc::Layout) -> Result<NonNull<[u8]>, AllocError> {
346 let current = self.state.alloc_count.get();
347 self.state.alloc_count.set(current + 1);
348 if current >= self.state.fail_threshold.get() {
349 return Err(AllocError);
350 }
351 DefaultAllocator::default().allocate(layout)
352 }
353
354 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: core::alloc::Layout) {
355 unsafe { DefaultAllocator::default().deallocate(ptr, layout) }
356 }
357
358 unsafe fn grow(
359 &self,
360 ptr: NonNull<u8>,
361 old_layout: core::alloc::Layout,
362 new_layout: core::alloc::Layout,
363 ) -> Result<NonNull<[u8]>, AllocError> {
364 let current = self.state.alloc_count.get();
365 self.state.alloc_count.set(current + 1);
366 if current >= self.state.fail_threshold.get() {
367 return Err(AllocError);
368 }
369 unsafe { DefaultAllocator::default().grow(ptr, old_layout, new_layout) }
370 }
371
372 unsafe fn shrink(
373 &self,
374 ptr: NonNull<u8>,
375 old_layout: core::alloc::Layout,
376 new_layout: core::alloc::Layout,
377 ) -> Result<NonNull<[u8]>, AllocError> {
378 let current = self.state.alloc_count.get();
379 self.state.alloc_count.set(current + 1);
380 if current >= self.state.fail_threshold.get() {
381 return Err(AllocError);
382 }
383 unsafe { DefaultAllocator::default().shrink(ptr, old_layout, new_layout) }
384 }
385
386 fn allocate_zeroed(
387 &self,
388 layout: core::alloc::Layout,
389 ) -> Result<NonNull<[u8]>, AllocError> {
390 let current = self.state.alloc_count.get();
391 self.state.alloc_count.set(current + 1);
392 if current >= self.state.fail_threshold.get() {
393 return Err(AllocError);
394 }
395 DefaultAllocator::default().allocate_zeroed(layout)
396 }
397 }
398
399 #[derive(Debug, Eq, PartialEq)]
400 struct TestObject<'a> {
401 val: usize,
402 alive: bool,
403 state: &'a TestState,
404 }
405
406 impl<'a> TestObject<'a> {
407 fn new(val: usize, state: &'a TestState) -> Self {
408 state.live_obj_count.set(state.live_obj_count.get() + 1);
409 state.ctor_count.set(state.ctor_count.get() + 1);
410 TestObject { val, alive: true, state }
411 }
412 }
413
414 impl<'a> Drop for TestObject<'a> {
415 fn drop(&mut self) {
416 if self.alive {
417 self.state.live_obj_count.set(self.state.live_obj_count.get() - 1);
418 self.state.dtor_count.set(self.state.dtor_count.get() + 1);
419 }
420 }
421 }
422
423 #[test]
424 fn test_empty_array() {
425 let a: Array<u32> = Array::new();
426 assert_eq!(a.len(), 0);
427 assert!(a.is_empty());
428 }
429
430 #[test]
431 fn test_try_new() {
432 let a = Array::<u32>::try_new(5).unwrap();
433 assert_eq!(a.len(), 5);
434 for i in 0..5 {
435 assert_eq!(a[i], 0);
436 }
437 }
438
439 #[test]
440 fn test_deref() {
441 let mut a = Array::<u32>::try_new(2).unwrap();
442 a[0] = 10;
443 a[1] = 20;
444
445 let slice: &[u32] = &a;
446 assert_eq!(slice, &[10, 20]);
447
448 let slice_mut: &mut [u32] = &mut a;
449 slice_mut[0] = 30;
450 assert_eq!(a[0], 30);
451 }
452
453 #[test]
454 fn test_drop_behavior() {
455 let state = TestState::default();
456 {
457 let mut b = Box::<[TestObject<'_>], TestAllocator<'_>>::try_new_uninit_slice_in(
458 2,
459 TestAllocator { state: &state },
460 )
461 .unwrap();
462 b[0].write(TestObject::new(1, &state));
463 b[1].write(TestObject::new(2, &state));
464 let _a = Array::from_box(unsafe { b.assume_init() });
465 assert_eq!(state.live_obj_count.get(), 2);
466 }
467 assert_eq!(state.live_obj_count.get(), 0);
468 assert_eq!(state.dtor_count.get(), 2);
469 }
470
471 #[test]
472 fn test_allocation_failure() {
473 let state = TestState::default();
474 state.fail_threshold.set(0); let res = Array::<u32, TestAllocator<'_>>::try_new_in(5, TestAllocator { state: &state });
477 assert!(res.is_err());
478 }
479
480 #[test]
481 fn test_try_new_zero_sized() {
482 let state = TestState::default();
483 let a = Array::<u32, TestAllocator<'_>>::try_new_in(0, TestAllocator { state: &state })
484 .unwrap();
485 assert_eq!(a.len(), 0);
486 assert!(a.is_empty());
487 }
488
489 #[test]
490 fn test_non_trivial_default() {
491 #[derive(Debug, PartialEq, Eq)]
492 struct MyInt {
493 value: i32,
494 }
495 impl Default for MyInt {
496 fn default() -> Self {
497 Self { value: 42 }
498 }
499 }
500
501 let a = Array::<MyInt>::try_new(5).unwrap();
502 assert_eq!(a.len(), 5);
503 for i in 0..5 {
504 assert_eq!(a[i].value, 42);
505 }
506 }
507
508 #[test]
509 fn test_array_new_in() {
510 let state = TestState::default();
511 let alloc = TestAllocator { state: &state };
512 let a = Array::<u32, TestAllocator<'_>>::new_in(alloc.clone());
513 assert!(a.is_empty());
514 }
515
516 #[test]
517 fn test_array_default() {
518 let a_def: Array<u32> = Default::default();
519 assert!(a_def.is_empty());
520 }
521
522 #[test]
523 fn test_array_into_box() {
524 let a_try = Array::<u32>::try_new(3).unwrap();
525 let b = a_try.into_box();
526 assert_eq!(b.len(), 3);
527 }
528
529 #[test]
530 fn test_array_test_allocator_happy() {
531 use kalloc::Allocator;
532 let state = TestState::default();
533 let alloc = TestAllocator { state: &state };
534 let layout = core::alloc::Layout::new::<u32>();
535 let ptr = alloc.allocate_zeroed(layout).unwrap();
536
537 let ptr = unsafe {
538 alloc.grow(ptr.cast(), layout, core::alloc::Layout::array::<u32>(2).unwrap()).unwrap()
539 };
540
541 let ptr = unsafe {
542 alloc.shrink(ptr.cast(), core::alloc::Layout::array::<u32>(2).unwrap(), layout).unwrap()
543 };
544
545 unsafe {
546 alloc.deallocate(ptr.cast(), layout);
547 }
548 }
549
550 #[test]
551 fn test_array_test_allocator_failure() {
552 use kalloc::Allocator;
553 let state = TestState::default();
554 let alloc = TestAllocator { state: &state };
555 let layout = core::alloc::Layout::new::<u32>();
556
557 state.fail_threshold.set(0);
559
560 assert!(alloc.allocate_zeroed(layout).is_err());
561
562 let dummy_ptr = core::ptr::NonNull::<u8>::dangling();
563 assert!(
564 unsafe {
565 alloc.grow(dummy_ptr.cast(), layout, core::alloc::Layout::array::<u32>(2).unwrap())
566 }
567 .is_err()
568 );
569 assert!(
570 unsafe {
571 alloc.shrink(
572 dummy_ptr.cast(),
573 core::alloc::Layout::array::<u32>(2).unwrap(),
574 layout,
575 )
576 }
577 .is_err()
578 );
579 }
580
581 #[test]
582 fn test_try_new_zeroed_slice() {
583 let arr = Array::<u32>::try_new_zeroed_slice(4).unwrap();
584 assert_eq!(arr.len(), 4);
585 for &val in arr.iter() {
586 assert_eq!(val, 0);
587 }
588
589 let state = TestState::default();
590 let arr_alloc = Array::<u32, TestAllocator<'_>>::try_new_zeroed_slice_in(
591 3,
592 TestAllocator { state: &state },
593 )
594 .unwrap();
595 assert_eq!(arr_alloc.len(), 3);
596 assert_eq!(state.alloc_count.get(), 1);
597 for &val in arr_alloc.iter() {
598 assert_eq!(val, 0);
599 }
600 }
601
602 #[test]
603 fn test_try_new_uninit_slice_and_assume_init() {
604 let mut uninit = Array::<u32>::try_new_uninit_slice(3).unwrap();
605 assert_eq!(uninit.len(), 3);
606 for i in 0..3 {
607 uninit[i].write((i * 10) as u32);
608 }
609 let arr = unsafe { uninit.assume_init() };
610 assert_eq!(arr.len(), 3);
611 assert_eq!(&arr[..], &[0, 10, 20]);
612 }
613
614 #[test]
615 fn test_uninit_slice_drop_behavior() {
616 let state = TestState::default();
617 {
618 let mut uninit = Array::<TestObject<'_>, TestAllocator<'_>>::try_new_uninit_slice_in(
619 2,
620 TestAllocator { state: &state },
621 )
622 .unwrap();
623 uninit[0].write(TestObject::new(10, &state));
624 uninit[1].write(TestObject::new(20, &state));
625 let arr = unsafe { uninit.assume_init() };
626 assert_eq!(state.live_obj_count.get(), 2);
627 assert_eq!(arr[0].val, 10);
628 assert_eq!(arr[1].val, 20);
629 }
630 assert_eq!(state.live_obj_count.get(), 0);
631 assert_eq!(state.dtor_count.get(), 2);
632 }
633
634 #[test]
635 fn test_into_and_from_raw_parts() {
636 let mut arr = Array::<u32>::try_new(3).unwrap();
637 arr[0] = 100;
638 arr[1] = 200;
639 arr[2] = 300;
640
641 let (ptr, len) = arr.into_raw_parts();
642 assert_eq!(len, 3);
643 assert!(!ptr.is_null());
644
645 let reconstructed = unsafe { Array::<u32>::from_raw_parts(ptr, len) };
646 assert_eq!(reconstructed.len(), 3);
647 assert_eq!(&reconstructed[..], &[100, 200, 300]);
648 }
649
650 #[test]
651 fn test_into_and_from_raw() {
652 let mut arr = Array::<u32>::try_new(2).unwrap();
653 arr[0] = 42;
654 arr[1] = 84;
655
656 let slice_ptr = arr.into_raw();
657 assert_eq!(unsafe { &*slice_ptr }, &[42, 84]);
658
659 let reconstructed = unsafe { Array::<u32>::from_raw(slice_ptr) };
660 assert_eq!(&reconstructed[..], &[42, 84]);
661 }
662
663 #[test]
664 fn test_raw_parts_with_allocator() {
665 let state = TestState::default();
666 let alloc = TestAllocator { state: &state };
667 let mut arr = Array::<u32, TestAllocator<'_>>::try_new_in(2, alloc.clone()).unwrap();
668 arr[0] = 7;
669 arr[1] = 9;
670
671 let (ptr, len, returned_alloc) = arr.into_raw_parts_with_allocator();
672 assert_eq!(len, 2);
673
674 let reconstructed =
675 unsafe { Array::<u32, TestAllocator<'_>>::from_raw_parts_in(ptr, len, returned_alloc) };
676 assert_eq!(&reconstructed[..], &[7, 9]);
677 }
678
679 #[pin_init::pin_data]
681 struct SelfAddressed {
682 addr: *mut SelfAddressed,
683 #[pin]
684 _pin: core::marker::PhantomPinned,
685 }
686
687 impl SelfAddressed {
688 fn new() -> impl PinInit<Self, Infallible> {
689 pin_init::pin_init!(&this in Self {
690 addr: this.as_ptr(),
691 _pin: core::marker::PhantomPinned,
692 })
693 }
694
695 fn is_at_initial_address(&self) -> bool {
696 core::ptr::eq(self.addr, self)
697 }
698 }
699
700 #[test]
701 fn test_try_new_pin_init() {
702 let mut init_count = 0;
703 let arr = Array::<SelfAddressed>::try_new_pin_init(5, || {
704 init_count += 1;
705 SelfAddressed::new()
706 })
707 .unwrap();
708 assert_eq!(init_count, 5);
709 assert_eq!(arr.len(), 5);
710 assert!(arr.iter().all(SelfAddressed::is_at_initial_address));
711
712 let moved = arr;
714 assert!(moved.iter().all(SelfAddressed::is_at_initial_address));
715 }
716
717 #[test]
718 fn test_try_new_pin_init_zero_sized() {
719 let mut init_count = 0;
720 let arr = Array::<SelfAddressed>::try_new_pin_init(0, || {
721 init_count += 1;
722 SelfAddressed::new()
723 })
724 .unwrap();
725 assert_eq!(init_count, 0);
726 assert!(arr.is_empty());
727 }
728
729 #[test]
730 fn test_try_new_pin_init_allocation_failure() {
731 let state = TestState::default();
732 state.fail_threshold.set(0); let mut init_count = 0;
735 let res = Array::<SelfAddressed, TestAllocator<'_>>::try_new_pin_init_in(
736 5,
737 || {
738 init_count += 1;
739 SelfAddressed::new()
740 },
741 TestAllocator { state: &state },
742 );
743 assert!(res.is_err());
744 assert_eq!(init_count, 0);
745 }
746
747 #[test]
748 fn test_try_new_pin_init_drop_behavior() {
749 let state = TestState::default();
750 {
751 let mut next_val = 0;
752 let arr = Array::<TestObject<'_>, TestAllocator<'_>>::try_new_pin_init_in(
753 3,
754 || {
755 next_val += 1;
756 TestObject::new(next_val, &state)
757 },
758 TestAllocator { state: &state },
759 )
760 .unwrap();
761 assert_eq!(state.alloc_count.get(), 1);
762 assert_eq!(state.live_obj_count.get(), 3);
763 assert_eq!(arr.iter().map(|obj| obj.val).sum::<usize>(), 1 + 2 + 3);
764 }
765 assert_eq!(state.live_obj_count.get(), 0);
766 assert_eq!(state.dtor_count.get(), 3);
767 }
768
769 #[test]
770 fn test_into_pin() {
771 let mut arr = Array::<u32>::try_new(2).unwrap();
772 arr[0] = 1;
773 arr[1] = 2;
774 let elements: *const u32 = arr.as_ptr();
775
776 let mut pinned = arr.into_pin();
777 assert!(core::ptr::eq(pinned.as_ptr(), elements));
778 assert_eq!(&pinned[..], &[1, 2]);
779
780 pinned.as_mut().get_mut()[0] = 3;
782 assert_eq!(&pinned[..], &[3, 2]);
783 }
784}