mod arena; mod global; pub use arena::*; pub use global::*; use std::{alloc::Layout, mem::MaybeUninit}; pub type DropFn = Option; pub struct AllocationEntry { ptr: *mut u8, layout: Layout, drop_fn: DropFn, } unsafe impl Send for AllocationEntry {} unsafe impl Sync for AllocationEntry {} pub trait Allocator { unsafe fn alloc_unsafe(&self, data: *const u8, layout: Layout, drop: DropFn) -> *mut u8; } pub trait SyncAllocator: Allocator + Send + Sync {} impl SyncAllocator for T {} impl<'l> dyn Allocator + 'l { pub fn alloc(&'l self, value: T) -> &'l mut T { unsafe { let value = MaybeUninit::new(value); let data = value.as_ptr() as *const u8; let layout = Layout::new::(); let drop: DropFn = match std::mem::needs_drop::() { false => None, true => Some(|ptr: *mut u8| std::ptr::drop_in_place(ptr as *mut T)), }; &mut *(self.alloc_unsafe(data, layout, drop) as *mut T) } } pub fn alloc_str(&'l self, str: &str) -> &'l str { unsafe { let ptr = self.alloc_unsafe(str.as_ptr(), Layout::array::(str.len()).unwrap(), None); let slice = std::slice::from_raw_parts_mut(ptr, str.len()); slice.copy_from_slice(str.as_bytes()); std::str::from_utf8_unchecked(slice) } } } impl<'l> dyn SyncAllocator + 'l { pub fn alloc(&'l self, value: T) -> &'l mut T { ::alloc(self, value) } pub fn alloc_str(&'l self, value: &str) -> &'l str { ::alloc_str(self, value) } }