bump_scope/features/
nightly_allocator_api.rs

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