bump_scope/
without_dealloc.rs

1use core::{alloc::Layout, ptr::NonNull};
2
3use crate::{
4    BumpAllocator,
5    alloc::{AllocError, Allocator},
6    polyfill::non_null,
7};
8
9/// Wraps a bump allocator and does nothing on [`deallocate`](Allocator::deallocate).
10///
11/// This type only implements [`Allocator`] for wrapped types that implement [`BumpAllocator`], so you don't accidentally leak memory.
12#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub struct WithoutDealloc<A>(pub A);
14
15unsafe impl<A: BumpAllocator> Allocator for WithoutDealloc<A> {
16    #[inline(always)]
17    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
18        self.0.allocate(layout)
19    }
20
21    #[inline(always)]
22    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
23        self.0.allocate_zeroed(layout)
24    }
25
26    #[inline(always)]
27    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
28        let _ = (ptr, layout);
29    }
30
31    #[inline(always)]
32    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
33        unsafe { self.0.grow(ptr, old_layout, new_layout) }
34    }
35
36    #[inline(always)]
37    unsafe fn grow_zeroed(
38        &self,
39        ptr: NonNull<u8>,
40        old_layout: Layout,
41        new_layout: Layout,
42    ) -> Result<NonNull<[u8]>, AllocError> {
43        unsafe { self.0.grow_zeroed(ptr, old_layout, new_layout) }
44    }
45
46    #[inline(always)]
47    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
48        unsafe { self.0.shrink(ptr, old_layout, new_layout) }
49    }
50}
51
52/// Wraps a bump allocator and does nothing on [`shrink`](Allocator::shrink).
53///
54/// This type only implements [`Allocator`] for wrapped types that implement [`BumpAllocator`], so you don't accidentally leak memory.
55#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
56pub struct WithoutShrink<A>(pub A);
57
58unsafe impl<A: BumpAllocator> Allocator for WithoutShrink<A> {
59    #[inline(always)]
60    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
61        self.0.allocate(layout)
62    }
63
64    #[inline(always)]
65    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
66        self.0.allocate_zeroed(layout)
67    }
68
69    #[inline(always)]
70    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
71        unsafe { self.0.deallocate(ptr, layout) };
72    }
73
74    #[inline(always)]
75    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
76        unsafe { self.0.grow(ptr, old_layout, new_layout) }
77    }
78
79    #[inline(always)]
80    unsafe fn grow_zeroed(
81        &self,
82        ptr: NonNull<u8>,
83        old_layout: Layout,
84        new_layout: Layout,
85    ) -> Result<NonNull<[u8]>, AllocError> {
86        unsafe { self.0.grow_zeroed(ptr, old_layout, new_layout) }
87    }
88
89    #[inline(always)]
90    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
91        #[cold]
92        #[inline(never)]
93        unsafe fn shrink_unfit<A: BumpAllocator>(
94            this: &WithoutShrink<A>,
95            ptr: NonNull<u8>,
96            old_layout: Layout,
97            new_layout: Layout,
98        ) -> Result<NonNull<[u8]>, AllocError> {
99            let new_ptr = this.0.allocate(new_layout)?.cast::<u8>();
100            unsafe { ptr.copy_to_nonoverlapping(new_ptr, old_layout.size()) };
101            Ok(NonNull::slice_from_raw_parts(new_ptr, new_layout.size()))
102        }
103
104        unsafe {
105            if non_null::is_aligned_to(ptr, new_layout.align()) {
106                Ok(NonNull::slice_from_raw_parts(ptr, new_layout.size()))
107            } else {
108                // expected to virtually never occur
109                shrink_unfit(self, ptr, old_layout, new_layout)
110            }
111        }
112    }
113}