1use std::{
2 mem::{self, MaybeUninit},
3 ptr::{NonNull, slice_from_raw_parts_mut},
4};
5
6pub(crate) struct ArenaChunk<T> {
7 elements: NonNull<[MaybeUninit<T>]>,
8 len: usize,
9}
10
11impl<T> ArenaChunk<T> {
12 pub fn new(len: usize) -> Self {
13 let array = Box::new_uninit_slice(len);
14 let elements = Box::into_raw(array);
15 let elements = unsafe { NonNull::new_unchecked(elements) };
16 Self { elements, len: 0 }
17 }
18
19 #[inline]
20 pub const fn capacity(&self) -> usize { self.elements.len() }
21
22 #[inline]
23 pub const fn start(&mut self) -> *mut T { self.elements.as_ptr() as *mut T }
24
25 #[inline]
26 pub const fn end(&mut self) -> *mut T {
27 unsafe {
28 if size_of::<T>() == 0 {
29 core::ptr::without_provenance_mut(!0)
30 } else {
31 self.start().add(self.elements.len())
32 }
33 }
34 }
35
36 #[inline]
37 pub fn add_len(&mut self, len: usize) { self.len += len; }
38
39 pub fn can_alloc(&self, ammount: usize) -> bool { self.len + ammount <= self.capacity() }
40}
41
42impl<T> Drop for ArenaChunk<T> {
43 fn drop(&mut self) {
44 let ptr = unsafe { self.elements.as_mut() };
45 let ptr = slice_from_raw_parts_mut(ptr.as_mut_ptr(), ptr.len());
46 if mem::needs_drop::<T>() {
47 for i in 0..self.len {
48 unsafe {
49 (*ptr)[i].assume_init_drop();
50 }
51 }
52 }
53 let elems = unsafe { Box::from_raw(ptr) };
54 drop(elems);
55 }
56}