bump_scope/features/
allocator_api2_02.rs

1use core::{
2    alloc::Layout,
3    ptr::{self, NonNull},
4};
5
6use allocator_api2_02::alloc::{AllocError, Allocator};
7
8#[cfg(feature = "alloc")]
9#[cfg(not(feature = "nightly-allocator-api"))]
10use allocator_api2_02::{alloc::Global, boxed::Box};
11
12use crate::alloc::{AllocError as CrateAllocError, Allocator as CrateAllocator};
13
14#[cfg(not(feature = "nightly-allocator-api"))]
15use crate::{Bump, BumpAllocator, BumpScope, MinimumAlignment, SupportedMinimumAlignment, WithoutDealloc, WithoutShrink};
16
17#[cfg(feature = "alloc")]
18#[cfg(not(feature = "nightly-allocator-api"))]
19use crate::alloc::{BoxLike, box_like};
20
21#[cfg(any(test, not(feature = "nightly-allocator-api")))]
22use crate::BaseAllocator;
23
24#[cfg(feature = "alloc")]
25#[cfg(not(feature = "nightly-allocator-api"))]
26unsafe impl CrateAllocator for Global {
27    #[inline(always)]
28    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, CrateAllocError> {
29        <Self as Allocator>::allocate(self, layout).map_err(Into::into)
30    }
31
32    #[inline(always)]
33    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
34        unsafe { <Self as Allocator>::deallocate(self, ptr, layout) };
35    }
36
37    #[inline(always)]
38    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, CrateAllocError> {
39        <Self as Allocator>::allocate_zeroed(self, layout).map_err(Into::into)
40    }
41
42    #[inline(always)]
43    unsafe fn grow(
44        &self,
45        ptr: NonNull<u8>,
46        old_layout: Layout,
47        new_layout: Layout,
48    ) -> Result<NonNull<[u8]>, CrateAllocError> {
49        unsafe { <Self as Allocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
50    }
51
52    #[inline(always)]
53    unsafe fn grow_zeroed(
54        &self,
55        ptr: NonNull<u8>,
56        old_layout: Layout,
57        new_layout: Layout,
58    ) -> Result<NonNull<[u8]>, CrateAllocError> {
59        unsafe { <Self as Allocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
60    }
61
62    #[inline(always)]
63    unsafe fn shrink(
64        &self,
65        ptr: NonNull<u8>,
66        old_layout: Layout,
67        new_layout: Layout,
68    ) -> Result<NonNull<[u8]>, CrateAllocError> {
69        unsafe { <Self as Allocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
70    }
71
72    #[inline(always)]
73    fn by_ref(&self) -> &Self
74    where
75        Self: Sized,
76    {
77        self
78    }
79}
80
81/// Wraps an <code>allocator_api2::alloc::[Allocator](Allocator)</code> to implement
82/// <code>bump_scope::alloc::[Allocator](CrateAllocator)</code> and vice versa.
83///
84/// # Example
85///
86/// ```
87/// # use allocator_api2_02 as allocator_api2;
88/// # use core::{alloc::Layout, ptr::NonNull};
89/// # use allocator_api2::alloc::{AllocError, Global};
90/// use allocator_api2::alloc::Allocator;
91///
92/// use bump_scope::{Bump, alloc::compat::AllocatorApi2V02Compat};
93///
94/// #[derive(Clone)]
95/// struct MyAllocatorApi2Allocator;
96///
97/// unsafe impl Allocator for MyAllocatorApi2Allocator {
98/// # /*
99///     ...
100/// # */
101/// #   fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
102/// #       <Global as Allocator>::allocate(&Global, layout)
103/// #   }
104/// #       
105/// #   unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
106/// #       <Global as Allocator>::deallocate(&Global, ptr, layout)
107/// #   }
108/// }
109///
110/// let bump: Bump<_> = Bump::new_in(AllocatorApi2V02Compat(MyAllocatorApi2Allocator));
111/// # _ = bump;
112/// ```
113#[repr(transparent)]
114#[derive(Debug, Default, Clone)]
115pub struct AllocatorApi2V02Compat<A: ?Sized>(pub A);
116
117impl<A: ?Sized> AllocatorApi2V02Compat<A> {
118    #[inline(always)]
119    #[expect(missing_docs)]
120    pub fn from_ref(allocator: &A) -> &Self {
121        unsafe { &*(ptr::from_ref(allocator) as *const Self) }
122    }
123
124    #[inline(always)]
125    #[expect(missing_docs)]
126    pub fn from_mut(allocator: &mut A) -> &mut Self {
127        unsafe { &mut *(ptr::from_mut(allocator) as *mut Self) }
128    }
129}
130
131unsafe impl<A: ?Sized + Allocator> CrateAllocator for AllocatorApi2V02Compat<A> {
132    #[inline(always)]
133    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, CrateAllocError> {
134        <A as Allocator>::allocate(&self.0, layout).map_err(Into::into)
135    }
136
137    #[inline(always)]
138    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
139        unsafe { <A as Allocator>::deallocate(&self.0, ptr, layout) };
140    }
141
142    #[inline(always)]
143    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, CrateAllocError> {
144        <A as Allocator>::allocate_zeroed(&self.0, layout).map_err(Into::into)
145    }
146
147    #[inline(always)]
148    unsafe fn grow(
149        &self,
150        ptr: NonNull<u8>,
151        old_layout: Layout,
152        new_layout: Layout,
153    ) -> Result<NonNull<[u8]>, CrateAllocError> {
154        unsafe { <A as Allocator>::grow(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
155    }
156
157    #[inline(always)]
158    unsafe fn grow_zeroed(
159        &self,
160        ptr: NonNull<u8>,
161        old_layout: Layout,
162        new_layout: Layout,
163    ) -> Result<NonNull<[u8]>, CrateAllocError> {
164        unsafe { <A as Allocator>::grow_zeroed(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
165    }
166
167    #[inline(always)]
168    unsafe fn shrink(
169        &self,
170        ptr: NonNull<u8>,
171        old_layout: Layout,
172        new_layout: Layout,
173    ) -> Result<NonNull<[u8]>, CrateAllocError> {
174        unsafe { <A as Allocator>::shrink(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
175    }
176
177    #[inline(always)]
178    fn by_ref(&self) -> &Self
179    where
180        Self: Sized,
181    {
182        self
183    }
184}
185
186unsafe impl<A: ?Sized + CrateAllocator> Allocator for AllocatorApi2V02Compat<A> {
187    #[inline(always)]
188    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
189        <A as CrateAllocator>::allocate(&self.0, layout).map_err(Into::into)
190    }
191
192    #[inline(always)]
193    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
194        unsafe { <A as CrateAllocator>::deallocate(&self.0, ptr, layout) };
195    }
196
197    #[inline(always)]
198    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
199        <A as CrateAllocator>::allocate_zeroed(&self.0, layout).map_err(Into::into)
200    }
201
202    #[inline(always)]
203    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
204        unsafe { <A as CrateAllocator>::grow(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
205    }
206
207    #[inline(always)]
208    unsafe fn grow_zeroed(
209        &self,
210        ptr: NonNull<u8>,
211        old_layout: Layout,
212        new_layout: Layout,
213    ) -> Result<NonNull<[u8]>, AllocError> {
214        unsafe { <A as CrateAllocator>::grow_zeroed(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
215    }
216
217    #[inline(always)]
218    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
219        unsafe { <A as CrateAllocator>::shrink(&self.0, ptr, old_layout, new_layout).map_err(Into::into) }
220    }
221
222    #[inline(always)]
223    fn by_ref(&self) -> &Self
224    where
225        Self: Sized,
226    {
227        self
228    }
229}
230
231#[cfg(not(feature = "nightly-allocator-api"))]
232impl From<AllocError> for CrateAllocError {
233    #[inline(always)]
234    fn from(_: AllocError) -> Self {
235        CrateAllocError
236    }
237}
238
239#[cfg(not(feature = "nightly-allocator-api"))]
240impl From<CrateAllocError> for AllocError {
241    #[inline(always)]
242    fn from(_: CrateAllocError) -> Self {
243        AllocError
244    }
245}
246
247#[cfg(not(feature = "nightly-allocator-api"))]
248unsafe impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Allocator
249    for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
250where
251    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
252    A: BaseAllocator<GUARANTEED_ALLOCATED>,
253{
254    #[inline(always)]
255    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
256        <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
257    }
258
259    #[inline(always)]
260    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
261        unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
262    }
263
264    #[inline(always)]
265    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
266        unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
267    }
268
269    #[inline(always)]
270    unsafe fn grow_zeroed(
271        &self,
272        ptr: NonNull<u8>,
273        old_layout: Layout,
274        new_layout: Layout,
275    ) -> Result<NonNull<[u8]>, AllocError> {
276        unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
277    }
278
279    #[inline(always)]
280    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
281        unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
282    }
283}
284
285#[cfg(not(feature = "nightly-allocator-api"))]
286unsafe impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Allocator
287    for &mut BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
288where
289    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
290    A: BaseAllocator<GUARANTEED_ALLOCATED>,
291{
292    #[inline(always)]
293    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
294        <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
295    }
296
297    #[inline(always)]
298    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
299        unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
300    }
301
302    #[inline(always)]
303    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
304        unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
305    }
306
307    #[inline(always)]
308    unsafe fn grow_zeroed(
309        &self,
310        ptr: NonNull<u8>,
311        old_layout: Layout,
312        new_layout: Layout,
313    ) -> Result<NonNull<[u8]>, AllocError> {
314        unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
315    }
316
317    #[inline(always)]
318    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
319        unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
320    }
321}
322
323#[cfg(not(feature = "nightly-allocator-api"))]
324unsafe impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Allocator
325    for Bump<A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
326where
327    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
328    A: BaseAllocator<GUARANTEED_ALLOCATED>,
329{
330    #[inline(always)]
331    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
332        <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
333    }
334
335    #[inline(always)]
336    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
337        unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
338    }
339
340    #[inline(always)]
341    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
342        unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
343    }
344
345    #[inline(always)]
346    unsafe fn grow_zeroed(
347        &self,
348        ptr: NonNull<u8>,
349        old_layout: Layout,
350        new_layout: Layout,
351    ) -> Result<NonNull<[u8]>, AllocError> {
352        unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
353    }
354
355    #[inline(always)]
356    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
357        unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
358    }
359}
360
361#[cfg(not(feature = "nightly-allocator-api"))]
362unsafe impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Allocator
363    for &mut Bump<A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
364where
365    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
366    A: BaseAllocator<GUARANTEED_ALLOCATED>,
367{
368    #[inline(always)]
369    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
370        <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
371    }
372
373    #[inline(always)]
374    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
375        unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
376    }
377
378    #[inline(always)]
379    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
380        unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
381    }
382
383    #[inline(always)]
384    unsafe fn grow_zeroed(
385        &self,
386        ptr: NonNull<u8>,
387        old_layout: Layout,
388        new_layout: Layout,
389    ) -> Result<NonNull<[u8]>, AllocError> {
390        unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
391    }
392
393    #[inline(always)]
394    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
395        unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
396    }
397}
398
399#[cfg(not(feature = "nightly-allocator-api"))]
400unsafe impl<A: BumpAllocator> Allocator for WithoutShrink<A> {
401    #[inline(always)]
402    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
403        <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
404    }
405
406    #[inline(always)]
407    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
408        unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
409    }
410
411    #[inline(always)]
412    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
413        unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
414    }
415
416    #[inline(always)]
417    unsafe fn grow_zeroed(
418        &self,
419        ptr: NonNull<u8>,
420        old_layout: Layout,
421        new_layout: Layout,
422    ) -> Result<NonNull<[u8]>, AllocError> {
423        unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
424    }
425
426    #[inline(always)]
427    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
428        unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
429    }
430}
431
432#[cfg(not(feature = "nightly-allocator-api"))]
433unsafe impl<A: BumpAllocator> Allocator for WithoutDealloc<A> {
434    #[inline(always)]
435    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
436        <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
437    }
438
439    #[inline(always)]
440    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
441        unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
442    }
443
444    #[inline(always)]
445    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
446        unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
447    }
448
449    #[inline(always)]
450    unsafe fn grow_zeroed(
451        &self,
452        ptr: NonNull<u8>,
453        old_layout: Layout,
454        new_layout: Layout,
455    ) -> Result<NonNull<[u8]>, AllocError> {
456        unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
457    }
458
459    #[inline(always)]
460    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
461        unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
462    }
463}
464
465#[cfg(feature = "alloc")]
466#[cfg(not(feature = "nightly-allocator-api"))]
467impl<T: ?Sized, A: Allocator> box_like::Sealed for Box<T, A> {
468    type T = T;
469    type A = A;
470
471    unsafe fn from_raw_in(ptr: *mut Self::T, allocator: Self::A) -> Self {
472        unsafe { Box::from_raw_in(ptr, allocator) }
473    }
474}
475
476#[cfg(feature = "alloc")]
477#[cfg(not(feature = "nightly-allocator-api"))]
478impl<T: ?Sized, A: Allocator> BoxLike for Box<T, A> {}
479
480#[test]
481fn test_compat() {
482    fn is_base_allocator<T: BaseAllocator>(_: T) {}
483
484    #[derive(Clone)]
485    struct TestAllocator;
486
487    unsafe impl Allocator for TestAllocator {
488        fn allocate(&self, _: Layout) -> Result<NonNull<[u8]>, AllocError> {
489            unimplemented!()
490        }
491
492        unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {
493            unimplemented!()
494        }
495    }
496
497    #[cfg(feature = "alloc")]
498    #[cfg(not(feature = "nightly-allocator-api"))]
499    is_base_allocator(Global);
500    is_base_allocator(AllocatorApi2V02Compat(TestAllocator));
501    is_base_allocator(AllocatorApi2V02Compat::from_ref(&TestAllocator));
502}