#[cfg(test)] pub(crate) use self::inner::AllocError; pub(crate) use self::inner::{Allocator, Global, do_alloc}; // Nightly-case. // Use unstable `allocator_api` feature. // This is compatible with `allocator-api2` which can be enabled or not. // This is used when building for `std`. #[cfg(feature = "nightly")] mod inner { use core::ptr::NonNull; #[cfg(test)] pub(crate) use stdalloc::alloc::AllocError; use stdalloc::alloc::Layout; pub(crate) use stdalloc::alloc::{Allocator, Global}; pub(crate) fn do_alloc(alloc: &A, layout: Layout) -> Result, ()> { match alloc.allocate(layout) { Ok(ptr) => Ok(ptr), Err(_) => Err(()), } } } // Basic non-nightly case. // This uses `allocator-api2` enabled by default. // If any crate enables "nightly" in `allocator-api2`, // this will be equivalent to the nightly case, // since `allocator_api2::alloc::Allocator` would be re-export of // `core::alloc::Allocator`. #[cfg(all(not(feature = "nightly"), feature = "allocator-api2"))] mod inner { #[cfg(test)] pub(crate) use allocator_api2::alloc::AllocError; pub(crate) use allocator_api2::alloc::{Allocator, Global}; use core::ptr::NonNull; use stdalloc::alloc::Layout; pub(crate) fn do_alloc(alloc: &A, layout: Layout) -> Result, ()> { match alloc.allocate(layout) { Ok(ptr) => Ok(ptr), Err(_) => Err(()), } } } // No-defaults case. // When building with default-features turned off and // neither `nightly` nor `allocator-api2` is enabled, // this will be used. // Making it impossible to use any custom allocator with collections defined // in this crate. // Any crate in build-tree can enable `allocator-api2`, // or `nightly` without disturbing users that don't want to use it. #[cfg(not(any(feature = "nightly", feature = "allocator-api2")))] mod inner { use core::ptr::NonNull; use stdalloc::alloc::{Layout, alloc, dealloc}; #[expect(clippy::missing_safety_doc)] // not exposed outside of this crate pub unsafe trait Allocator { fn allocate(&self, layout: Layout) -> Result, ()>; unsafe fn deallocate(&self, ptr: NonNull, layout: Layout); } #[derive(Copy, Clone)] pub struct Global; unsafe impl Allocator for Global { #[inline] fn allocate(&self, layout: Layout) -> Result, ()> { match unsafe { NonNull::new(alloc(layout)) } { Some(data) => { // SAFETY: this is NonNull::slice_from_raw_parts. Ok(unsafe { NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut( data.as_ptr(), layout.size(), )) }) } None => Err(()), } } #[inline] unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { unsafe { dealloc(ptr.as_ptr(), layout); } } } impl Default for Global { #[inline] fn default() -> Self { Global } } pub(crate) fn do_alloc(alloc: &A, layout: Layout) -> Result, ()> { alloc.allocate(layout) } }