use crate::{
bump::{Bump, BumpSlice, BumpView},
unsync,
};
use allocator_api2::alloc::{AllocError, Allocator, Layout};
use core::ptr::NonNull;
unsafe impl<T> Allocator for Bump<T> {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
Allocator::allocate(&self.as_view(), layout)
}
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {}
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { Allocator::shrink(&self.as_view(), ptr, old_layout, new_layout) }
}
}
unsafe impl Allocator for BumpSlice {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
Allocator::allocate(&self.as_view(), layout)
}
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {}
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { Allocator::shrink(&self.as_view(), ptr, old_layout, new_layout) }
}
}
unsafe impl Allocator for BumpView<'_> {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
let len = layout.size();
match self.get_layout(layout) {
None => Err(AllocError),
Some(allocation) => Ok(NonNull::slice_from_raw_parts(allocation.ptr, len)),
}
}
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {}
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { shrink_in_place(ptr, old_layout, new_layout) }
}
}
unsafe impl<T> Allocator for unsync::Bump<T> {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
<unsync::BumpSlice as Allocator>::allocate(self, layout)
}
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {}
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { <unsync::BumpSlice as Allocator>::shrink(self, ptr, old_layout, new_layout) }
}
}
unsafe impl Allocator for unsync::BumpSlice {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
let len = layout.size();
match self.alloc(layout) {
None => Err(AllocError),
Some(allocation) => Ok(NonNull::slice_from_raw_parts(allocation, len)),
}
}
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {}
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { shrink_in_place(ptr, old_layout, new_layout) }
}
}
unsafe fn shrink_in_place(
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
debug_assert!(new_layout.size() <= old_layout.size());
let len = new_layout.size();
let offset = ptr.align_offset(new_layout.align());
if offset > 0 {
if old_layout
.size()
.checked_sub(offset)
.is_none_or(|n| n < len)
{
return Err(AllocError);
}
let dst = unsafe { ptr.byte_add(offset) };
unsafe { ptr.copy_to(dst, len) };
dst
} else {
ptr
};
Ok(NonNull::slice_from_raw_parts(ptr, len))
}