pub use std::{alloc::Layout, ptr::NonNull};
#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
pub enum AllocationError {
SizeIsZero,
SizeTooLarge,
AlignmentFailure,
OutOfMemory,
InternalError,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum AllocationGrowError {
ProvidedPointerNotContainedInAllocator,
GrowWouldShrink,
SizeIsZero,
OutOfMemory,
AlignmentFailure,
InternalError,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum AllocationShrinkError {
ProvidedPointerNotContainedInAllocator,
ShrinkWouldGrow,
SizeIsZero,
AlignmentFailure,
InternalError,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum DeallocationError {
ProvidedPointerNotContainedInAllocator,
InternalError,
}
pub trait BaseAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocationError>;
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocationError> {
let memory = self.allocate(layout)?;
unsafe {
std::ptr::write_bytes(
memory.as_ref().as_ptr() as *mut u8,
0,
memory.as_ref().len(),
)
};
Ok(memory)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) -> Result<(), DeallocationError>;
}
pub trait Allocator: BaseAllocator {
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocationGrowError>;
unsafe fn grow_zeroed(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocationGrowError> {
let memory = self.grow(ptr, old_layout, new_layout)?;
std::ptr::write_bytes(
memory.as_ref().as_ptr().add(old_layout.size()) as *mut u8,
0,
memory.as_ref().len() - old_layout.size(),
);
Ok(memory)
}
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocationShrinkError>;
}