bump_scope/features/
allocator_util.rs1macro_rules! allocator_compat_wrapper {
3 (
4 $(#[$attr:meta])*
5 struct $struct:ident for $othr:ident
6 ) => {
7 $(#[$attr])*
8 #[repr(transparent)]
9 #[derive(Debug, Default, Clone)]
10 pub struct $struct<A: ?Sized>(pub A);
11
12 impl<A: ?Sized> $struct<A> {
13 #[inline(always)]
14 #[expect(missing_docs)]
15 pub fn from_ref(allocator: &A) -> &Self {
16 unsafe { &*(core::ptr::from_ref(allocator) as *const Self) }
17 }
18
19 #[inline(always)]
20 #[expect(missing_docs)]
21 pub fn from_mut(allocator: &mut A) -> &mut Self {
22 unsafe { &mut *(core::ptr::from_mut(allocator) as *mut Self) }
23 }
24 }
25
26 impl_allocator_via_allocator! {
27 self;
28
29 use {&self.0} for crate as $othr impl[A: ?Sized + $othr::alloc::Allocator] $struct<A>
30 use {&self.0} for $othr as crate impl[A: ?Sized + crate::alloc::Allocator] $struct<A>
31 }
32
33 #[test]
34 fn test_compat() {
35 use core::{alloc::Layout, ptr::NonNull};
36
37 #[derive(Clone)]
38 struct OthrAllocator;
39
40 unsafe impl $othr::alloc::Allocator for OthrAllocator {
41 fn allocate(&self, _: Layout) -> Result<NonNull<[u8]>, $othr::alloc::AllocError> {
42 unimplemented!()
43 }
44
45 unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {
46 unimplemented!()
47 }
48 }
49
50 fn is_base_allocator<T: $crate::alloc::Allocator>(_: T) {}
51
52 #[cfg(feature = "alloc")]
53 is_base_allocator(Global);
54 is_base_allocator($struct(OthrAllocator));
55 is_base_allocator($struct::from_ref(&OthrAllocator));
56
57 struct CrateAllocator;
58
59 unsafe impl $crate::alloc::Allocator for CrateAllocator {
60 fn allocate(&self, _: Layout) -> Result<NonNull<[u8]>, $crate::alloc::AllocError> {
61 unimplemented!()
62 }
63
64 unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {
65 unimplemented!()
66 }
67 }
68
69 fn is_othr_allocator<T: $othr::alloc::Allocator>(_: T) {}
70
71 is_othr_allocator($struct(CrateAllocator));
72 is_othr_allocator($struct::from_ref(&CrateAllocator));
73 }
74 };
75}
76macro_rules! impl_allocator_via_allocator {
79 (
80 $self:ident;
81 $(
82 $(#[$attr:meta])*
83 use {$accessor:expr} for $target_crate:ident as $source_crate:ident
84 impl [$($($args:tt)+)?]
85 $ty:ty
86 $(where [$($bounds:tt)*])?
87 )*
88 ) => {
89 $(
90 const _: () = {
91 use core::{alloc::Layout, ptr::NonNull};
92
93 use $target_crate::alloc::{
94 Allocator as TargetAllocator,
95 AllocError as TargetAllocError,
96 };
97
98 use $source_crate::alloc::{
99 Allocator as SourceAllocator,
100 };
101
102 $(#[$attr])*
103 unsafe impl $(<$($args)*>)? TargetAllocator for $ty
104 $(where $($bounds)*)?
105 {
106 #[inline(always)]
107 fn allocate(&$self, layout: Layout) -> Result<NonNull<[u8]>, TargetAllocError> {
108 SourceAllocator::allocate($accessor, layout).map_err(Into::into)
109 }
110
111 #[inline(always)]
112 unsafe fn deallocate(&$self, ptr: NonNull<u8>, layout: Layout) {
113 unsafe { SourceAllocator::deallocate($accessor, ptr, layout) };
114 }
115
116 #[inline(always)]
117 unsafe fn grow(
118 &$self,
119 ptr: NonNull<u8>,
120 old_layout: Layout,
121 new_layout: Layout,
122 ) -> Result<NonNull<[u8]>, TargetAllocError> {
123 unsafe { SourceAllocator::grow($accessor, ptr, old_layout, new_layout).map_err(Into::into) }
124 }
125
126 #[inline(always)]
127 unsafe fn grow_zeroed(
128 &$self,
129 ptr: NonNull<u8>,
130 old_layout: Layout,
131 new_layout: Layout,
132 ) -> Result<NonNull<[u8]>, TargetAllocError> {
133 unsafe {
134 SourceAllocator::grow_zeroed($accessor, ptr, old_layout, new_layout).map_err(Into::into)
135 }
136 }
137
138 #[inline(always)]
139 unsafe fn shrink(
140 &$self,
141 ptr: NonNull<u8>,
142 old_layout: Layout,
143 new_layout: Layout,
144 ) -> Result<NonNull<[u8]>, TargetAllocError> {
145 unsafe { SourceAllocator::shrink($accessor, ptr, old_layout, new_layout).map_err(Into::into) }
146 }
147 }
148 };
149 )*
150 };
151}
152
153pub(crate) use allocator_compat_wrapper;
154pub(crate) use impl_allocator_via_allocator;