use core::alloc::Layout;
use core::error::Error;
use core::fmt;
use core::ptr::NonNull;
pub unsafe trait Allocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, AllocError>;
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Global;
unsafe impl Allocator for Global {
fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, AllocError> {
if layout.size() == 0 {
return Err(AllocError);
}
NonNull::new(unsafe { alloc::alloc::alloc(layout) }).ok_or(AllocError)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
unsafe { alloc::alloc::dealloc(ptr.as_ptr(), layout) }
}
}
unsafe impl<A: Allocator + ?Sized> Allocator for &A {
fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, AllocError> {
(**self).allocate(layout)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
unsafe { (**self).deallocate(ptr, layout) }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct AllocError;
impl fmt::Display for AllocError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("memory allocation failed")
}
}
impl Error for AllocError {}