use core::ptr::NonNull;
use crate::allocator::alloc::{Layout, LayoutError};
#[cfg(feature = "allocator-api")]
use crate::allocator::alloc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AllocError;
impl From<LayoutError> for AllocError {
fn from(_: LayoutError) -> Self {
AllocError
}
}
#[cfg(feature = "allocator-api")]
impl From<alloc::AllocError> for AllocError {
fn from(_: alloc::AllocError) -> Self {
AllocError
}
}
pub unsafe trait AllocatorProvider {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>;
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unsafe {
debug_assert!(
new_layout.size() >= old_layout.size(),
"`new_layout.size()` must be greater than or equal to `old_layout.size()`"
);
let new_ptr = self.allocate(new_layout)?;
core::ptr::copy_nonoverlapping(
ptr.as_ptr(),
new_ptr.as_ptr().cast(),
old_layout.size(),
);
self.deallocate(ptr, old_layout);
Ok(new_ptr)
}
}
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
_old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
Ok(NonNull::slice_from_raw_parts(ptr, new_layout.size()))
}
#[inline(always)]
fn by_ref(&self) -> &Self
where
Self: Sized,
{
self
}
fn handle_alloc_error(&self, layout: Layout) -> ! {
panic!("allocation error: {:?}", layout);
}
}
#[cfg(feature = "allocator-api")]
unsafe impl<A> AllocatorProvider for A
where
A: alloc::Allocator,
{
#[inline]
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
(*self).allocate(layout).map_err(Into::into)
}
#[inline]
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
unsafe { (*self).deallocate(ptr, layout) }
}
#[inline]
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { (*self).grow(ptr, old_layout, new_layout).map_err(Into::into) }
}
#[inline]
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { (*self).shrink(ptr, old_layout, new_layout).map_err(Into::into) }
}
}