bump_scope/features/
allocator_api2_03.rs

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