arena/
chunk.rs

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}