#[allow(unsafe_code)] mod arena { use std::alloc; use std::marker::PhantomData; const PAGE_SIZE: usize = 4096; const MAX_PAGE_SIZE: usize = 512 * PAGE_SIZE; pub struct Arena<'arena> { offset: usize, block: Block<'arena>, phantom: PhantomData<&'arena ()>, } #[derive(Copy, Clone)] struct Block<'arena> { data: *mut u8, layout: alloc::Layout, prev: Option<&'arena Block<'arena>>, } impl<'arena> Arena<'arena> { pub fn new() -> Arena<'arena> { Arena { offset: 0, block: Block::alloc(PAGE_SIZE), phantom: PhantomData } } pub fn alloc(&mut self, val: T) -> &'arena T { let offset = self.offset_raw::(std::mem::size_of::()); unsafe { *offset = val; &*offset } } pub fn alloc_slice(&mut self, val: &[T]) -> &'arena [T] { let offset = self.offset_raw::(std::mem::size_of_val(val)); unsafe { std::ptr::copy_nonoverlapping(val.as_ptr(), offset, val.len()); std::slice::from_raw_parts(offset as *const T, val.len()) } } pub fn alloc_slice_with_value(&mut self, val: T, len: usize) -> &'arena [T] { let offset = self.offset_raw::(len * std::mem::size_of::()); unsafe { let write_ptr = offset; for idx in 0..len { std::ptr::write(write_ptr.add(idx), val); } std::slice::from_raw_parts(offset as *const T, len) } } pub fn alloc_str(&mut self, val: &str) -> &'arena str { let bytes = self.alloc_slice(val.as_bytes()); unsafe { std::str::from_utf8_unchecked(bytes) } } fn offset_raw(&mut self, size: usize) -> *mut T { let align = align_of::(); self.offset = (self.offset + align - 1) & !(align - 1); if self.offset + size > self.block.layout.size() { self.grow(size); } unsafe { let offset = self.block.data.add(self.offset) as *mut T; self.offset += size; offset } } fn grow(&mut self, size: usize) { let prev = self.block; let block_size = (self.block.layout.size() * 2).min(MAX_PAGE_SIZE).max(size); self.offset = 0; self.block = Block::alloc(block_size); self.block.prev = Some(self.alloc(prev)); } pub fn mem_usage(&self) -> (usize, usize) { let mut total = 0; let mut current = Some(self.block); while let Some(block) = current { total += block.layout.size(); current = block.prev.copied(); } (total - self.block.layout.size() + self.offset, total) } } impl<'arena> Block<'arena> { fn alloc(size: usize) -> Block<'arena> { let layout = alloc::Layout::from_size_align(size, PAGE_SIZE).unwrap(); let data = unsafe { alloc::alloc(layout) }; Block { data, layout, prev: None } } fn dealloc(&self) { unsafe { alloc::dealloc(self.data, self.layout) } } } impl Drop for Arena<'_> { fn drop(&mut self) { let mut current = Some(self.block); while let Some(block) = current { current = block.prev.copied(); block.dealloc(); } } } }