bump_scope/features/
allocator_api2_04.rs

1use core::{
2    alloc::Layout,
3    ptr::{self, NonNull},
4};
5
6use allocator_api2_04::alloc::{AllocError, Allocator};
7
8#[cfg(feature = "alloc")]
9use allocator_api2_04::{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_04 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::AllocatorApi2V04Compat};
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(AllocatorApi2V04Compat(MyAllocatorApi2Allocator));
106/// # _ = bump;
107/// ```
108#[repr(transparent)]
109#[derive(Debug, Default, Clone)]
110pub struct AllocatorApi2V04Compat<A: ?Sized>(pub A);
111
112impl<A: ?Sized> AllocatorApi2V04Compat<A> {
113    #[inline(always)]
114    #[expect(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    #[expect(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 AllocatorApi2V04Compat<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 AllocatorApi2V04Compat<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 Bump<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: BumpAllocatorExt> Allocator for WithoutShrink<A> {
315    #[inline(always)]
316    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
317        <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
318    }
319
320    #[inline(always)]
321    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
322        unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
323    }
324
325    #[inline(always)]
326    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
327        unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
328    }
329
330    #[inline(always)]
331    unsafe fn grow_zeroed(
332        &self,
333        ptr: NonNull<u8>,
334        old_layout: Layout,
335        new_layout: Layout,
336    ) -> Result<NonNull<[u8]>, AllocError> {
337        unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
338    }
339
340    #[inline(always)]
341    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
342        unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
343    }
344}
345
346unsafe impl<A: BumpAllocatorExt> Allocator for WithoutDealloc<A> {
347    #[inline(always)]
348    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
349        <Self as CrateAllocator>::allocate(self, layout).map_err(Into::into)
350    }
351
352    #[inline(always)]
353    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
354        unsafe { <Self as CrateAllocator>::deallocate(self, ptr, layout) };
355    }
356
357    #[inline(always)]
358    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
359        unsafe { <Self as CrateAllocator>::grow(self, ptr, old_layout, new_layout).map_err(Into::into) }
360    }
361
362    #[inline(always)]
363    unsafe fn grow_zeroed(
364        &self,
365        ptr: NonNull<u8>,
366        old_layout: Layout,
367        new_layout: Layout,
368    ) -> Result<NonNull<[u8]>, AllocError> {
369        unsafe { <Self as CrateAllocator>::grow_zeroed(self, ptr, old_layout, new_layout).map_err(Into::into) }
370    }
371
372    #[inline(always)]
373    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
374        unsafe { <Self as CrateAllocator>::shrink(self, ptr, old_layout, new_layout).map_err(Into::into) }
375    }
376}
377
378#[cfg(feature = "alloc")]
379impl<T: ?Sized, A: Allocator> box_like::Sealed for Box<T, A> {
380    type T = T;
381    type A = A;
382
383    #[inline(always)]
384    unsafe fn from_raw_in(ptr: *mut Self::T, allocator: Self::A) -> Self {
385        unsafe { Box::from_raw_in(ptr, allocator) }
386    }
387}
388
389#[cfg(feature = "alloc")]
390impl<T: ?Sized, A: Allocator> BoxLike for Box<T, A> {}
391
392#[test]
393fn test_compat() {
394    fn is_base_allocator<T: BaseAllocator>(_: T) {}
395
396    #[derive(Clone)]
397    struct TestAllocator;
398
399    unsafe impl Allocator for TestAllocator {
400        fn allocate(&self, _: Layout) -> Result<NonNull<[u8]>, AllocError> {
401            unimplemented!()
402        }
403
404        unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout) {
405            unimplemented!()
406        }
407    }
408
409    #[cfg(feature = "alloc")]
410    is_base_allocator(Global);
411    is_base_allocator(AllocatorApi2V04Compat(TestAllocator));
412    is_base_allocator(AllocatorApi2V04Compat::from_ref(&TestAllocator));
413}