#![no_std]
use core::{cell::RefCell, mem::MaybeUninit};
pub mod boxed;
pub struct Arena<T, const N: usize> {
storage: RefCell<Chunk<T, N>>,
}
impl<T, const N: usize> Arena<T, N> {
pub const fn new() -> Self {
Self {
storage: RefCell::new(Chunk::new()),
}
}
pub fn alloc(&self, item: T) -> Result<&mut T, T> {
let mut storage = self.storage.borrow_mut();
let len = storage.len();
storage.push(item)?;
Ok(unsafe { &mut *storage.as_mut_ptr().add(len) })
}
}
struct Chunk<T, const N: usize> {
buffer: [MaybeUninit<T>; N],
len: usize,
}
impl<T, const N: usize> Chunk<T, N> {
const ELEM: MaybeUninit<T> = MaybeUninit::uninit();
const INIT: [MaybeUninit<T>; N] = [Self::ELEM; N];
pub const fn new() -> Self {
Self {
buffer: Self::INIT,
len: 0,
}
}
pub const fn len(&self) -> usize {
self.len
}
pub fn push(&mut self, item: T) -> Result<(), T> {
if self.len < N {
unsafe {
*self.buffer.get_unchecked_mut(self.len) = MaybeUninit::new(item);
self.len += 1;
}
Ok(())
} else {
Err(item)
}
}
pub fn as_mut_ptr(&mut self) -> *mut T {
self.buffer.as_mut_ptr() as *mut T
}
}