New paste Repaste Download
#[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<T: Copy>(&mut self, val: T) -> &'arena T {
            let offset = self.offset_raw::<T>(std::mem::size_of::<T>());
            unsafe {
                *offset = val;
                &*offset
            }
        }
        pub fn alloc_slice<T: Copy>(&mut self, val: &[T]) -> &'arena [T] {
            let offset = self.offset_raw::<T>(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<T: Copy>(&mut self, val: T, len: usize) -> &'arena [T] {
            let offset = self.offset_raw::<T>(len * std::mem::size_of::<T>());
            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<T: Copy>(&mut self, size: usize) -> *mut T {
            let align = align_of::<T>();
            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();
            }
        }
    }
}
Filename: arena. Size: 4kb. View raw, , hex, or download this file.

This paste expires on 2025-07-03 22:34:01.783646. Pasted through web.