diff --git a/static-alloc/Cargo.toml b/static-alloc/Cargo.toml index 7c7b087..50579da 100644 --- a/static-alloc/Cargo.toml +++ b/static-alloc/Cargo.toml @@ -18,6 +18,7 @@ all-features = true [dependencies] alloc-traits = { path = "../alloc-traits", version = "0.1.0" } portable-atomic = { version = "1", optional = true, default-features = false } +allocator-api2 = { version = "0.4", optional = true, default-features = false } [features] alloc = [] diff --git a/static-alloc/src/allocator_api2.rs b/static-alloc/src/allocator_api2.rs new file mode 100644 index 0000000..5e319fe --- /dev/null +++ b/static-alloc/src/allocator_api2.rs @@ -0,0 +1,90 @@ +use crate::bump::{Bump, BumpSlice, BumpView}; + +use allocator_api2::alloc::{AllocError, Allocator, Layout}; +use core::ptr::NonNull; + +unsafe impl Allocator for Bump { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + Allocator::allocate(&self.as_view(), layout) + } + + unsafe fn deallocate(&self, _: NonNull, _: Layout) {} + + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // Safety: passing along requirements. These two allocators serve the same allocations, a + // property we permit for these two of our own types. + unsafe { Allocator::shrink(&self.as_view(), ptr, old_layout, new_layout) } + } +} + +unsafe impl Allocator for BumpSlice { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + Allocator::allocate(&self.as_view(), layout) + } + + unsafe fn deallocate(&self, _: NonNull, _: Layout) {} + + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // Safety: passing along requirements. These two allocators serve the same allocations, a + // property we permit for these two of our own types. + unsafe { Allocator::shrink(&self.as_view(), ptr, old_layout, new_layout) } + } +} + +unsafe impl Allocator for BumpView<'_> { + fn allocate(&self, layout: Layout) -> Result, 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, _: Layout) {} + + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, 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) + { + // Won't fit in-place. Sorry. + return Err(AllocError); + } + + // Safety: in-bounds as we just verified that old layout has at least as many bytes as + // offset, and the caller was required to pass a live allocation with corresponding + // layout; implying that it also has that many bytes. + let dst = unsafe { ptr.byte_add(offset) }; + // Safety: just verified that layout has at least `len` bytes after the offset so `dst` + // also has provenance according to the caller's requirements. + unsafe { ptr.copy_to(dst, len) }; + dst + } else { + ptr + }; + + Ok(NonNull::slice_from_raw_parts(ptr, len)) + } +} diff --git a/static-alloc/src/bump.rs b/static-alloc/src/bump.rs index 39525ea..d4feeba 100644 --- a/static-alloc/src/bump.rs +++ b/static-alloc/src/bump.rs @@ -183,7 +183,7 @@ pub struct BumpSlice { /// /// Note: You might think that we can #[derive(Clone, Copy)] -struct BumpView<'lt> { +pub(crate) struct BumpView<'lt> { header: &'lt Header, storage: &'lt UnsafeCell<[MaybeUninit]>, } @@ -564,7 +564,7 @@ impl Bump { self.header = Header::empty(); } - fn as_view(&self) -> BumpView<'_> { + pub(crate) fn as_view(&self) -> BumpView<'_> { BumpView { header: &self.header, storage: { @@ -1028,7 +1028,7 @@ impl BumpSlice { self.header = Header::empty(); } - fn as_view(&self) -> BumpView<'_> { + pub(crate) fn as_view(&self) -> BumpView<'_> { BumpView { header: &self.header, storage: &self.storage, diff --git a/static-alloc/src/lib.rs b/static-alloc/src/lib.rs index d64f6a5..ea41cbd 100644 --- a/static-alloc/src/lib.rs +++ b/static-alloc/src/lib.rs @@ -47,6 +47,9 @@ #[cfg(feature = "alloc")] extern crate alloc; +#[cfg(feature = "allocator-api2")] +mod allocator_api2; + pub mod bump; pub use bump::Bump; pub mod leaked;