| 1 | #[cfg (test)] |
| 2 | pub(crate) use self::inner::AllocError; |
| 3 | pub(crate) use self::inner::{do_alloc, Allocator, Global}; |
| 4 | |
| 5 | // Nightly-case. |
| 6 | // Use unstable `allocator_api` feature. |
| 7 | // This is compatible with `allocator-api2` which can be enabled or not. |
| 8 | // This is used when building for `std`. |
| 9 | #[cfg (feature = "nightly" )] |
| 10 | mod inner { |
| 11 | #[cfg (test)] |
| 12 | pub use crate::alloc::alloc::AllocError; |
| 13 | use crate::alloc::alloc::Layout; |
| 14 | pub use crate::alloc::alloc::{Allocator, Global}; |
| 15 | use core::ptr::NonNull; |
| 16 | |
| 17 | #[allow (clippy::map_err_ignore)] |
| 18 | pub(crate) fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> { |
| 19 | match alloc.allocate(layout) { |
| 20 | Ok(ptr: NonNull<[u8]>) => Ok(ptr.as_non_null_ptr()), |
| 21 | Err(_) => Err(()), |
| 22 | } |
| 23 | } |
| 24 | } |
| 25 | |
| 26 | // Basic non-nightly case. |
| 27 | // This uses `allocator-api2` enabled by default. |
| 28 | // If any crate enables "nightly" in `allocator-api2`, |
| 29 | // this will be equivalent to the nightly case, |
| 30 | // since `allocator_api2::alloc::Allocator` would be re-export of |
| 31 | // `core::alloc::Allocator`. |
| 32 | #[cfg (all(not(feature = "nightly" ), feature = "allocator-api2" ))] |
| 33 | mod inner { |
| 34 | use crate::alloc::alloc::Layout; |
| 35 | #[cfg (test)] |
| 36 | pub use allocator_api2::alloc::AllocError; |
| 37 | pub use allocator_api2::alloc::{Allocator, Global}; |
| 38 | use core::ptr::NonNull; |
| 39 | |
| 40 | #[allow (clippy::map_err_ignore)] |
| 41 | pub(crate) fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> { |
| 42 | match alloc.allocate(layout) { |
| 43 | Ok(ptr) => Ok(ptr.cast()), |
| 44 | Err(_) => Err(()), |
| 45 | } |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | // No-defaults case. |
| 50 | // When building with default-features turned off and |
| 51 | // neither `nightly` nor `allocator-api2` is enabled, |
| 52 | // this will be used. |
| 53 | // Making it impossible to use any custom allocator with collections defined |
| 54 | // in this crate. |
| 55 | // Any crate in build-tree can enable `allocator-api2`, |
| 56 | // or `nightly` without disturbing users that don't want to use it. |
| 57 | #[cfg (not(any(feature = "nightly" , feature = "allocator-api2" )))] |
| 58 | mod inner { |
| 59 | use crate::alloc::alloc::{alloc, dealloc, Layout}; |
| 60 | use core::ptr::NonNull; |
| 61 | |
| 62 | #[allow (clippy::missing_safety_doc)] // not exposed outside of this crate |
| 63 | pub unsafe trait Allocator { |
| 64 | fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()>; |
| 65 | unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout); |
| 66 | } |
| 67 | |
| 68 | #[derive (Copy, Clone)] |
| 69 | pub struct Global; |
| 70 | |
| 71 | unsafe impl Allocator for Global { |
| 72 | #[inline ] |
| 73 | fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> { |
| 74 | unsafe { NonNull::new(alloc(layout)).ok_or(()) } |
| 75 | } |
| 76 | #[inline ] |
| 77 | unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { |
| 78 | dealloc(ptr.as_ptr(), layout); |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | impl Default for Global { |
| 83 | #[inline ] |
| 84 | fn default() -> Self { |
| 85 | Global |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | pub(crate) fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> { |
| 90 | alloc.allocate(layout) |
| 91 | } |
| 92 | } |
| 93 | |