Skip to main content

bump_scope/
bump.rs

1use core::{
2    alloc::Layout,
3    ffi::CStr,
4    fmt::{self, Debug},
5    mem::{ManuallyDrop, MaybeUninit},
6    panic::{RefUnwindSafe, UnwindSafe},
7    ptr::NonNull,
8};
9
10#[cfg(feature = "nightly-clone-to-uninit")]
11use core::clone::CloneToUninit;
12
13use crate::{
14    BaseAllocator, BumpBox, BumpClaimGuard, BumpScope, BumpScopeGuard, Checkpoint, ErrorBehavior,
15    alloc::{AllocError, Allocator},
16    allocator_impl,
17    chunk::ChunkSize,
18    maybe_default_allocator,
19    owned_slice::OwnedSlice,
20    polyfill::{transmute_mut, transmute_ref, transmute_value},
21    raw_bump::RawBump,
22    settings::{BumpAllocatorSettings, BumpSettings, False, MinimumAlignment, SupportedMinimumAlignment},
23    stats::{AnyStats, Stats},
24    traits::{
25        self, BumpAllocator, BumpAllocatorCore, BumpAllocatorScope, BumpAllocatorTyped, BumpAllocatorTypedScope,
26        MutBumpAllocatorTypedScope,
27    },
28};
29
30#[cfg(feature = "panic-on-alloc")]
31use crate::panic_on_error;
32
33macro_rules! make_type {
34    ($($allocator_parameter:tt)*) => {
35        /// The bump allocator.
36        ///
37        /// # Generic parameters
38        /// - **`A`** — the base allocator, defaults to `Global` when the `alloc` feature is enabled
39        /// - **`S`** — the bump allocator settings, see [`settings`](crate::settings)
40        ///
41        /// # Overview
42        /// All of the mentioned methods that do allocations panic if the base allocator returned an error.
43        /// For every such panicking method, there is a corresponding `try_`-prefixed version that returns a `Result` instead.
44        ///
45        /// #### Create a `Bump` ...
46        /// - with a default size hint: <code>[new]\([_in][new_in])</code> / <code>[default]</code>
47        /// - provide a size hint: <code>[with_size]\([_in][with_size_in])</code>
48        /// - provide a minimum capacity: <code>[with_capacity]\([_in][with_capacity_in])</code>
49        /// - const, without allocating a chunk: <code>[unallocated]</code>
50        ///
51        /// [new]: Bump::new
52        /// [new_in]: Bump::new_in
53        /// [default]: Bump::default
54        /// [with_size]: Bump::with_size
55        /// [with_size_in]: Bump::with_size_in
56        /// [with_capacity]: Bump::with_capacity
57        /// [with_capacity_in]: Bump::with_capacity_in
58        /// [unallocated]: Bump::unallocated
59        ///
60        /// #### Allocate ...
61        /// - sized values: [`alloc`], [`alloc_with`], [`alloc_default`], [`alloc_zeroed`]
62        /// - strings: [`alloc_str`], <code>[alloc_fmt](BumpAllocatorTypedScope::alloc_fmt)([_mut](MutBumpAllocatorTypedScope::alloc_fmt_mut))</code>
63        /// - c strings: [`alloc_cstr`], [`alloc_cstr_from_str`], <code>[alloc_cstr_fmt](BumpAllocatorTypedScope::alloc_cstr_fmt)([_mut](MutBumpAllocatorTypedScope::alloc_cstr_fmt_mut))</code>
64        /// - slices: <code>alloc_slice_{[copy](BumpAllocatorTypedScope::alloc_slice_copy), [clone](BumpAllocatorTypedScope::alloc_slice_clone), [move](BumpAllocatorTypedScope::alloc_slice_move), [fill](BumpAllocatorTypedScope::alloc_slice_fill), [fill_with](BumpAllocatorTypedScope::alloc_slice_fill_with)}</code>,
65        ///   [`alloc_zeroed_slice`]
66        /// - slices from an iterator: [`alloc_iter`], [`alloc_iter_exact`], [`alloc_iter_mut`], [`alloc_iter_mut_rev`]
67        /// - uninitialized values: [`alloc_uninit`], [`alloc_uninit_slice`], [`alloc_uninit_slice_for`]
68        ///
69        ///   which can then be conveniently initialized by the [`init*` methods of `BumpBox`](crate::BumpBox#bumpbox-has-a-lot-of-methods).
70        /// - results: [`alloc_try_with`], [`alloc_try_with_mut`]
71        /// - via clone *(nightly only)*: [`alloc_clone`]
72        ///
73        /// #### Free memory using ...
74        /// - scopes: [`scoped`], [`scoped_aligned`], [`scope_guard`]
75        /// - checkpoints: [`checkpoint`], [`reset_to`]
76        /// - reset: [`reset`], [`reset_to_start`]
77        /// - dealloc: [`dealloc`]
78        ///
79        /// #### Configure allocator settings ...
80        /// - [`with_settings`], [`borrow_with_settings`], [`borrow_mut_with_settings`]
81        ///
82        /// ## Collections
83        /// A `Bump` (and [`BumpScope`]) can be used to allocate collections of this crate...
84        /// ```
85        /// use bump_scope::{Bump, BumpString};
86        /// let bump: Bump = Bump::new();
87        ///
88        /// let mut string = BumpString::new_in(&bump);
89        /// string.push_str("Hello,");
90        /// string.push_str(" world!");
91        /// ```
92        ///
93        /// ... and collections from crates that use `allocator_api2`'s `Allocator` like [hashbrown](https://docs.rs/hashbrown)'s [`HashMap`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html):
94        ///
95        /// *This requires the `allocator-api2-02` feature OR the `nightly-allocator-api` feature along with hashbrown's `nightly` feature.*
96        // NOTE: This code is tested in `crates/test-hashbrown/lib.rs`.
97        // It's not tested here because using hashbrown requires us to either have both the crate features for a nightly allocator api in bump-scope and hashbrown or neither.
98        // This could be solved by making bump-scope's "nightly-allocator-api" depend on "hashbrown/nightly" but that currently breaks tools like cargo-hack and cargo-minimal-versions.
99        /// ```
100        /// # /*
101        /// use bump_scope::Bump;
102        /// use hashbrown::HashMap;
103        ///
104        /// let bump: Bump = Bump::new();
105        /// let mut map = HashMap::new_in(&bump);
106        /// map.insert("tau", 6.283);
107        /// # */
108        /// # ()
109        /// ```
110        ///
111        /// On nightly and with the feature `nightly-allocator-api` you can also allocate collections from `std` that have an allocator parameter:
112        #[cfg_attr(feature = "nightly-allocator-api", doc = "```")]
113        #[cfg_attr(not(feature = "nightly-allocator-api"), doc = "```no_run")]
114        /// # /*
115        /// # those features are already been enabled by a `doc(test(attr`
116        /// # but we still want it here for demonstration
117        /// #![feature(allocator_api, btreemap_alloc)]
118        /// # */
119        /// # #[cfg(feature = "nightly-allocator-api")] fn main() {
120        /// use bump_scope::Bump;
121        /// use std::collections::{VecDeque, BTreeMap, LinkedList};
122        ///
123        /// let bump: Bump = Bump::new();
124        /// let vec = Vec::new_in(&bump);
125        /// let queue = VecDeque::new_in(&bump);
126        /// let map = BTreeMap::new_in(&bump);
127        /// let list = LinkedList::new_in(&bump);
128        /// # let _: Vec<i32, _> = vec;
129        /// # let _: VecDeque<i32, _> = queue;
130        /// # let _: BTreeMap<i32, i32, _> = map;
131        /// # let _: LinkedList<i32, _> = list;
132        /// # }
133        /// # #[cfg(not(feature = "nightly-allocator-api"))] fn main() {}
134        /// ```
135        ///
136        /// [`alloc`]: BumpAllocatorTypedScope::alloc
137        /// [`alloc_with`]: BumpAllocatorTypedScope::alloc_with
138        /// [`alloc_default`]: BumpAllocatorTypedScope::alloc_default
139        /// [`alloc_zeroed`]: crate::zerocopy_08::BumpAllocatorTypedScopeExt::alloc_zeroed
140        ///
141        /// [`alloc_str`]: BumpAllocatorTypedScope::alloc_str
142        ///
143        /// [`alloc_cstr`]: BumpAllocatorTypedScope::alloc_cstr
144        /// [`alloc_cstr_from_str`]: BumpAllocatorTypedScope::alloc_cstr_from_str
145        ///
146        /// [`alloc_zeroed_slice`]: crate::zerocopy_08::BumpAllocatorTypedScopeExt::alloc_zeroed_slice
147        ///
148        /// [`alloc_iter`]: BumpAllocatorTypedScope::alloc_iter
149        /// [`alloc_iter_exact`]: BumpAllocatorTypedScope::alloc_iter_exact
150        /// [`alloc_iter_mut`]: MutBumpAllocatorTypedScope::alloc_iter_mut
151        /// [`alloc_iter_mut_rev`]: MutBumpAllocatorTypedScope::alloc_iter_mut_rev
152        ///
153        /// [`alloc_uninit`]: BumpAllocatorTypedScope::alloc_uninit
154        /// [`alloc_uninit_slice`]: BumpAllocatorTypedScope::alloc_uninit_slice
155        /// [`alloc_uninit_slice_for`]: BumpAllocatorTypedScope::alloc_uninit_slice_for
156        ///
157        /// [`alloc_try_with`]: Bump::alloc_try_with
158        /// [`alloc_try_with_mut`]: Bump::alloc_try_with_mut
159        ///
160        /// [`alloc_clone`]: BumpAllocatorTypedScope::alloc_clone
161        ///
162        /// [`scoped`]: crate::traits::BumpAllocator::scoped
163        /// [`scoped_aligned`]: crate::traits::BumpAllocator::scoped_aligned
164        /// [`scope_guard`]: crate::traits::BumpAllocator::scope_guard
165        ///
166        /// [`checkpoint`]: BumpAllocatorCore::checkpoint
167        /// [`reset_to`]: BumpAllocatorCore::reset_to
168        ///
169        /// [`reset`]: Bump::reset
170        /// [`reset_to_start`]: Bump::reset_to_start
171        /// [`dealloc`]: BumpAllocatorTyped::dealloc
172        ///
173        /// [`aligned`]: BumpAllocatorScope::aligned
174        ///
175        /// [`with_settings`]: Bump::with_settings
176        /// [`borrow_with_settings`]: Bump::borrow_with_settings
177        /// [`borrow_mut_with_settings`]: Bump::borrow_with_settings
178        ///
179        /// # Gotcha
180        ///
181        /// Having live allocations and entering bump scopes at the same time requires a `BumpScope`.
182        /// This is due to the way lifetimes work, since `Bump` returns allocations with the lifetime
183        /// of its own borrow instead of a separate lifetime like `BumpScope` does.
184        ///
185        /// So you can't do this:
186        /// ```compile_fail,E0502
187        /// # use bump_scope::Bump;
188        /// let mut bump: Bump = Bump::new();
189        ///
190        /// let one = bump.alloc(1);
191        ///
192        /// bump.scoped(|bump| {
193        ///     // whatever
194        ///     # _ = bump;
195        /// });
196        /// # _ = one;
197        /// ```
198        /// But you can make the code work by converting the `Bump` it to a [`BumpScope`] first using [`as_mut_scope`]:
199        /// ```
200        /// # use bump_scope::Bump;
201        /// let mut bump: Bump = Bump::new();
202        /// let bump = bump.as_mut_scope();
203        ///
204        /// let one = bump.alloc(1);
205        ///
206        /// bump.scoped(|bump| {
207        ///     // whatever
208        ///     # _ = bump;
209        /// });
210        /// # _ = one;
211        /// ```
212        ///
213        /// [`as_mut_scope`]: Bump::as_mut_scope
214        #[repr(transparent)]
215        pub struct Bump<$($allocator_parameter)*, S = BumpSettings>
216        where
217            A: Allocator,
218            S: BumpAllocatorSettings,
219        {
220            pub(crate) raw: RawBump<A, S>,
221        }
222    };
223}
224
225maybe_default_allocator!(make_type);
226
227// Sending Bumps when nothing is allocated is fine.
228// When something is allocated Bump is borrowed and sending is not possible.
229unsafe impl<A, S> Send for Bump<A, S>
230where
231    A: Allocator,
232    S: BumpAllocatorSettings,
233{
234}
235
236impl<A, S> UnwindSafe for Bump<A, S>
237where
238    A: Allocator + UnwindSafe,
239    S: BumpAllocatorSettings,
240{
241}
242
243impl<A, S> RefUnwindSafe for Bump<A, S>
244where
245    A: Allocator + RefUnwindSafe,
246    S: BumpAllocatorSettings,
247{
248}
249
250impl<A, S> Drop for Bump<A, S>
251where
252    A: Allocator,
253    S: BumpAllocatorSettings,
254{
255    fn drop(&mut self) {
256        unsafe { self.raw.manually_drop() }
257    }
258}
259
260impl<A, S> Debug for Bump<A, S>
261where
262    A: Allocator,
263    S: BumpAllocatorSettings,
264{
265    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266        AnyStats::from(self.stats()).debug_format("Bump", f)
267    }
268}
269
270#[cfg(feature = "panic-on-alloc")]
271impl<A, S> Default for Bump<A, S>
272where
273    A: Allocator + Default,
274    S: BumpAllocatorSettings,
275{
276    /// With [`GUARANTEED_ALLOCATED`] this does the same as [`new`], otherwise it does the same as [`unallocated`].
277    ///
278    /// [`GUARANTEED_ALLOCATED`]: crate::settings
279    /// [`new`]: Bump::new
280    /// [`unallocated`]: Bump::unallocated
281    #[inline(always)]
282    fn default() -> Self {
283        if S::GUARANTEED_ALLOCATED {
284            Self::new_in(Default::default())
285        } else {
286            use core::{cell::Cell, marker::PhantomData};
287
288            use crate::{chunk::ChunkHeader, raw_bump::RawChunk};
289
290            Self {
291                raw: RawBump {
292                    chunk: Cell::new(RawChunk {
293                        header: ChunkHeader::unallocated::<S>().cast(),
294                        marker: PhantomData,
295                    }),
296                },
297            }
298        }
299    }
300}
301
302#[cfg(not(feature = "panic-on-alloc"))]
303impl<A, S> Default for Bump<A, S>
304where
305    A: Allocator + Default,
306    S: BumpAllocatorSettings<GuaranteedAllocated = False>,
307{
308    /// Does the same as [`unallocated`].
309    ///
310    /// [`unallocated`]: Bump::unallocated
311    #[inline(always)]
312    fn default() -> Self {
313        Self::unallocated()
314    }
315}
316
317impl<A, S> Bump<A, S>
318where
319    A: Allocator,
320    S: BumpAllocatorSettings<GuaranteedAllocated = False>,
321{
322    /// Constructs a new `Bump` without allocating a chunk.
323    ///
324    /// This requires the `GUARANTEED_ALLOCATED` setting to be `false`, see [`settings`].
325    ///
326    /// # Examples
327    ///
328    /// ```
329    /// use bump_scope::{
330    ///     alloc::Global,
331    ///     Bump,
332    ///     settings::{BumpSettings, BumpAllocatorSettings}
333    /// };
334    ///
335    /// type Settings = <BumpSettings as BumpAllocatorSettings>::WithGuaranteedAllocated<false>;
336    ///
337    /// let bump: Bump<Global, Settings> = Bump::unallocated();
338    /// # _ = bump;
339    /// ```
340    ///
341    /// [`settings`]: crate::settings
342    #[must_use]
343    pub const fn unallocated() -> Self {
344        Self { raw: RawBump::new() }
345    }
346}
347
348/// Methods for a `Bump` with a default base allocator.
349impl<A, S> Bump<A, S>
350where
351    A: Allocator + Default,
352    S: BumpAllocatorSettings,
353{
354    /// Constructs a new `Bump` with a default size hint for the first chunk.
355    ///
356    /// This is equivalent to <code>[with_size][]([MINIMUM_CHUNK_SIZE])</code>.
357    ///
358    /// # Panics
359    /// Panics if the allocation fails.
360    ///
361    /// # Examples
362    /// ```
363    /// use bump_scope::Bump;
364    ///
365    /// let bump: Bump = Bump::new();
366    /// # _ = bump;
367    /// ```
368    ///
369    /// [with_size]: Bump::with_size
370    /// [MINIMUM_CHUNK_SIZE]: crate::settings
371    #[must_use]
372    #[inline(always)]
373    #[cfg(feature = "panic-on-alloc")]
374    pub fn new() -> Self {
375        Self::with_size(S::MINIMUM_CHUNK_SIZE)
376    }
377
378    /// Constructs a new `Bump` with a default size hint for the first chunk.
379    ///
380    /// This is equivalent to <code>[try_with_size][]([MINIMUM_CHUNK_SIZE])</code>.
381    ///
382    /// # Errors
383    /// Errors if the allocation fails.
384    ///
385    /// # Examples
386    /// ```
387    /// use bump_scope::Bump;
388    ///
389    /// let bump: Bump = Bump::try_new()?;
390    /// # _ = bump;
391    /// # Ok::<(), bump_scope::alloc::AllocError>(())
392    /// ```
393    ///
394    /// [try_with_size]: Bump::try_with_size
395    /// [MINIMUM_CHUNK_SIZE]: crate::settings
396    #[inline(always)]
397    pub fn try_new() -> Result<Self, AllocError> {
398        Self::try_with_size(S::MINIMUM_CHUNK_SIZE)
399    }
400
401    /// Constructs a new `Bump` with a size hint for the first chunk.
402    ///
403    /// If you want to ensure a specific capacity, use [`with_capacity`](Self::with_capacity) instead.
404    ///
405    /// An effort is made to ensure the size requested from the base allocator is friendly to an allocator that uses size classes and stores metadata alongside allocations.
406    /// To achieve this, the requested size is rounded up to either the next power of two or the next multiple of `0x1000`, whichever is smaller.
407    /// After that, the size of `[usize; 2]` is subtracted.
408    ///
409    /// If the base allocator returns a memory block that is larger than requested, then the chunk will use the extra space.
410    ///
411    /// **Disclaimer:** The way in which the chunk layout is calculated might change.
412    /// Such a change is not considered semver breaking.
413    ///
414    /// # Panics
415    /// Panics if the allocation fails.
416    ///
417    /// # Examples
418    /// ```
419    /// use bump_scope::Bump;
420    ///
421    /// // `Bump` with a roughly 1 Mebibyte sized chunk
422    /// let bump_1mib: Bump = Bump::with_size(1024 * 1024);
423    /// # _ = bump_1mib;
424    /// ```
425    #[must_use]
426    #[inline(always)]
427    #[cfg(feature = "panic-on-alloc")]
428    pub fn with_size(size: usize) -> Self {
429        panic_on_error(Self::generic_with_size(size))
430    }
431
432    /// Constructs a new `Bump` with a size hint for the first chunk.
433    ///
434    /// If you want to ensure a specific capacity, use [`try_with_capacity`](Self::try_with_capacity) instead.
435    ///
436    /// An effort is made to ensure the size requested from the base allocator is friendly to an allocator that uses size classes and stores metadata alongside allocations.
437    /// To achieve this, the requested size is rounded up to either the next power of two or the next multiple of `0x1000`, whichever is smaller.
438    /// After that, the size of `[usize; 2]` is subtracted.
439    ///
440    /// If the base allocator returns a memory block that is larger than requested, then the chunk will use the extra space.
441    ///
442    /// **Disclaimer:** The way in which the chunk layout is calculated might change.
443    /// Such a change is not considered semver breaking.
444    ///
445    /// # Errors
446    /// Errors if the allocation fails.
447    ///
448    /// # Examples
449    /// ```
450    /// use bump_scope::Bump;
451    ///
452    /// // `Bump` with a roughly 1 Mebibyte sized chunk
453    /// let bump_1mib: Bump = Bump::try_with_size(1024 * 1024)?;
454    /// # _ = bump_1mib;
455    /// # Ok::<(), bump_scope::alloc::AllocError>(())
456    /// ```
457    #[inline(always)]
458    pub fn try_with_size(size: usize) -> Result<Self, AllocError> {
459        Self::generic_with_size(size)
460    }
461
462    #[inline]
463    pub(crate) fn generic_with_size<E: ErrorBehavior>(size: usize) -> Result<Self, E> {
464        Self::generic_with_size_in(size, Default::default())
465    }
466
467    /// Constructs a new `Bump` with a chunk that has at least enough space for `layout`.
468    ///
469    /// To construct a `Bump` with a size hint use <code>[with_size](Bump::with_size)</code> instead.
470    ///
471    /// # Panics
472    /// Panics if the allocation fails.
473    ///
474    /// # Examples
475    /// ```
476    /// use bump_scope::Bump;
477    /// use core::alloc::Layout;
478    ///
479    /// let layout = Layout::array::<u8>(1234).unwrap();
480    /// let bump: Bump = Bump::with_capacity(layout);
481    /// assert!(bump.stats().capacity() >= layout.size());
482    /// ```
483    #[must_use]
484    #[inline(always)]
485    #[cfg(feature = "panic-on-alloc")]
486    pub fn with_capacity(layout: Layout) -> Self {
487        panic_on_error(Self::generic_with_capacity(layout))
488    }
489
490    /// Constructs a new `Bump` with a chunk that has at least enough space for `layout`.
491    ///
492    /// To construct a `Bump` with a size hint use <code>[try_with_size](Bump::try_with_size)</code> instead.
493    ///
494    /// # Errors
495    /// Errors if the allocation fails.
496    ///
497    /// # Examples
498    /// ```
499    /// use bump_scope::Bump;
500    /// use core::alloc::Layout;
501    ///
502    /// let layout = Layout::array::<u8>(1234).unwrap();
503    /// let bump: Bump = Bump::try_with_capacity(layout)?;
504    /// assert!(bump.stats().capacity() >= layout.size());
505    /// # Ok::<(), bump_scope::alloc::AllocError>(())
506    /// ```
507    #[inline(always)]
508    pub fn try_with_capacity(layout: Layout) -> Result<Self, AllocError> {
509        Self::generic_with_capacity(layout)
510    }
511
512    #[inline]
513    pub(crate) fn generic_with_capacity<E: ErrorBehavior>(layout: Layout) -> Result<Self, E> {
514        Self::generic_with_capacity_in(layout, Default::default())
515    }
516}
517
518/// Methods that are always available.
519impl<A, S> Bump<A, S>
520where
521    A: Allocator,
522    S: BumpAllocatorSettings,
523{
524    /// Constructs a new `Bump` with a default size hint for the first chunk.
525    ///
526    /// This is equivalent to <code>[with_size_in][]([MINIMUM_CHUNK_SIZE], allocator)</code>.
527    ///
528    /// # Panics
529    /// Panics if the allocation fails.
530    ///
531    /// # Examples
532    /// ```
533    /// use bump_scope::Bump;
534    /// use bump_scope::alloc::Global;
535    ///
536    /// let bump: Bump = Bump::new_in(Global);
537    /// # _ = bump;
538    /// ```
539    ///
540    /// [with_size_in]: Bump::with_size_in
541    /// [MINIMUM_CHUNK_SIZE]: crate::settings
542    #[must_use]
543    #[inline(always)]
544    #[cfg(feature = "panic-on-alloc")]
545    pub fn new_in(allocator: A) -> Self {
546        Self::with_size_in(S::MINIMUM_CHUNK_SIZE, allocator)
547    }
548
549    /// Constructs a new `Bump` with a default size hint for the first chunk.
550    ///
551    /// This is equivalent to <code>[try_with_size_in][]([MINIMUM_CHUNK_SIZE], allocator)</code>.
552    ///
553    /// # Errors
554    /// Errors if the allocation fails.
555    ///
556    /// # Examples
557    /// ```
558    /// use bump_scope::Bump;
559    /// use bump_scope::alloc::Global;
560    ///
561    /// let bump: Bump = Bump::try_new_in(Global)?;
562    /// # _ = bump;
563    /// # Ok::<(), bump_scope::alloc::AllocError>(())
564    /// ```
565    ///
566    /// [try_with_size_in]: Bump::try_with_size_in
567    /// [MINIMUM_CHUNK_SIZE]: crate::settings
568    #[inline(always)]
569    pub fn try_new_in(allocator: A) -> Result<Self, AllocError> {
570        Self::try_with_size_in(S::MINIMUM_CHUNK_SIZE, allocator)
571    }
572
573    /// Constructs a new `Bump` with a size hint for the first chunk.
574    ///
575    /// If you want to ensure a specific capacity, use [`with_capacity_in`](Self::with_capacity_in) instead.
576    ///
577    /// An effort is made to ensure the size requested from the base allocator is friendly to an allocator that uses size classes and stores metadata alongside allocations.
578    /// To achieve this, the requested size is rounded up to either the next power of two or the next multiple of `0x1000`, whichever is smaller.
579    /// After that, the size of `[usize; 2]` is subtracted.
580    ///
581    /// If the base allocator returns a memory block that is larger than requested, then the chunk will use the extra space.
582    ///
583    /// **Disclaimer:** The way in which the chunk layout is calculated might change.
584    /// Such a change is not considered semver breaking.
585    ///
586    /// # Panics
587    /// Panics if the allocation fails.
588    ///
589    /// # Examples
590    /// ```
591    /// use bump_scope::Bump;
592    /// use bump_scope::alloc::Global;
593    ///
594    /// // `Bump` with a roughly 1 Mebibyte sized chunk
595    /// let bump_1mib: Bump = Bump::with_size_in(1024 * 1024, Global);
596    /// # _ = bump_1mib;
597    /// ```
598    #[must_use]
599    #[inline(always)]
600    #[cfg(feature = "panic-on-alloc")]
601    pub fn with_size_in(size: usize, allocator: A) -> Self {
602        panic_on_error(Self::generic_with_size_in(size, allocator))
603    }
604
605    /// Constructs a new `Bump` with a size hint for the first chunk.
606    ///
607    /// If you want to ensure a specific capacity, use [`try_with_capacity`](Self::try_with_capacity) instead.
608    ///
609    /// An effort is made to ensure the size requested from the base allocator is friendly to an allocator that uses size classes and stores metadata alongside allocations.
610    /// To achieve this, the requested size is rounded up to either the next power of two or the next multiple of `0x1000`, whichever is smaller.
611    /// After that, the size of `[usize; 2]` is subtracted.
612    ///
613    /// If the base allocator returns a memory block that is larger than requested, then the chunk will use the extra space.
614    ///
615    /// **Disclaimer:** The way in which the chunk layout is calculated might change.
616    /// Such a change is not considered semver breaking.
617    ///
618    /// # Errors
619    /// Errors if the allocation fails.
620    ///
621    /// # Examples
622    /// ```
623    /// use bump_scope::Bump;
624    /// use bump_scope::alloc::Global;
625    ///
626    /// // `Bump` with a roughly 1 Mebibyte sized chunk
627    /// let bump_1mib: Bump = Bump::try_with_size_in(1024 * 1024, Global)?;
628    /// # _ = bump_1mib;
629    /// # Ok::<(), bump_scope::alloc::AllocError>(())
630    /// ```
631    #[inline(always)]
632    pub fn try_with_size_in(size: usize, allocator: A) -> Result<Self, AllocError> {
633        Self::generic_with_size_in(size, allocator)
634    }
635
636    #[inline]
637    pub(crate) fn generic_with_size_in<E: ErrorBehavior>(size: usize, allocator: A) -> Result<Self, E> {
638        Ok(Self {
639            raw: RawBump::with_size(
640                ChunkSize::<A, S>::from_hint(size).ok_or_else(E::capacity_overflow)?,
641                allocator,
642            )?,
643        })
644    }
645
646    /// Constructs a new `Bump` with at least enough space for `layout`.
647    ///
648    /// To construct a `Bump` with a size hint use <code>[with_size_in](Bump::with_size_in)</code> instead.
649    ///
650    /// # Panics
651    /// Panics if the allocation fails.
652    ///
653    /// # Examples
654    /// ```
655    /// use bump_scope::Bump;
656    /// use bump_scope::alloc::Global;
657    /// use core::alloc::Layout;
658    ///
659    /// let layout = Layout::array::<u8>(1234).unwrap();
660    /// let bump: Bump = Bump::with_capacity_in(layout, Global);
661    /// assert!(bump.stats().capacity() >= layout.size());
662    /// # Ok::<(), bump_scope::alloc::AllocError>(())
663    /// ```
664    #[must_use]
665    #[inline(always)]
666    #[cfg(feature = "panic-on-alloc")]
667    pub fn with_capacity_in(layout: Layout, allocator: A) -> Self {
668        panic_on_error(Self::generic_with_capacity_in(layout, allocator))
669    }
670
671    /// Constructs a new `Bump` with at least enough space for `layout`.
672    ///
673    /// To construct a `Bump` with a size hint use <code>[try_with_size_in](Bump::try_with_size_in)</code> instead.
674    ///
675    /// # Errors
676    /// Errors if the allocation fails.
677    ///
678    /// # Examples
679    /// ```
680    /// use bump_scope::Bump;
681    /// use bump_scope::alloc::Global;
682    /// use core::alloc::Layout;
683    ///
684    /// let layout = Layout::array::<u8>(1234).unwrap();
685    /// let bump: Bump = Bump::try_with_capacity_in(layout, Global)?;
686    /// assert!(bump.stats().capacity() >= layout.size());
687    /// # Ok::<(), bump_scope::alloc::AllocError>(())
688    /// ```
689    #[inline(always)]
690    pub fn try_with_capacity_in(layout: Layout, allocator: A) -> Result<Self, AllocError> {
691        Self::generic_with_capacity_in(layout, allocator)
692    }
693
694    #[inline]
695    pub(crate) fn generic_with_capacity_in<E: ErrorBehavior>(layout: Layout, allocator: A) -> Result<Self, E> {
696        Ok(Self {
697            raw: RawBump::with_size(
698                ChunkSize::<A, S>::from_capacity(layout).ok_or_else(E::capacity_overflow)?,
699                allocator,
700            )?,
701        })
702    }
703
704    /// Resets this bump allocator and deallocates all but the largest chunk.
705    ///
706    /// This deallocates all allocations at once by resetting
707    /// the bump pointer to the start of the retained chunk.
708    ///
709    /// For a version of this function that doesn't deallocate chunks, see [`reset_to_start`].
710    ///
711    /// [`reset_to_start`]: Self::reset_to_start
712    ///
713    /// # Examples
714    ///
715    /// Basic usage:
716    ///
717    /// ```
718    /// # use bump_scope::Bump;
719    /// let mut scratch_allocator: Bump = Bump::new();
720    /// let items = [1, 2, 3];
721    ///
722    /// for item in items {
723    ///     // the scratch allocator is empty
724    ///     assert_eq!(scratch_allocator.stats().allocated(), 0);
725    ///
726    ///     // allocate on scratch allocator...
727    ///     let _ = scratch_allocator.alloc_fmt(format_args!("hello {item}"));
728    ///
729    ///     // reset the scratch allocator for the next iteration
730    ///     scratch_allocator.reset();
731    /// }
732    /// ```
733    ///
734    /// Detailed behavior:
735    ///
736    /// ```
737    /// # use bump_scope::Bump;
738    /// let mut bump: Bump = Bump::with_size(512);
739    ///
740    /// // won't fit in the first chunk, will be allocated in another chunk
741    /// bump.alloc_uninit_slice::<u8>(600);
742    ///
743    /// let chunks = bump.stats().small_to_big().collect::<Vec<_>>();
744    /// assert_eq!(chunks.len(), 2);
745    /// assert!(chunks[0].size() < chunks[1].size());
746    /// assert_eq!(chunks[0].allocated(), 0);
747    /// assert_eq!(chunks[1].allocated(), 600);
748    /// let last_chunk_size = chunks[1].size();
749    ///
750    /// bump.reset();
751    ///
752    /// let chunks = bump.stats().small_to_big().collect::<Vec<_>>();
753    /// assert_eq!(chunks.len(), 1);
754    /// assert_eq!(chunks[0].size(), last_chunk_size);
755    /// assert_eq!(chunks[0].allocated(), 0);
756    /// ```
757    #[inline(always)]
758    pub fn reset(&mut self) {
759        self.raw.reset();
760    }
761
762    /// Resets this bump allocator.
763    ///
764    /// This deallocates all allocations at once by resetting
765    /// the bump pointer to the start of the first chunk.
766    ///
767    /// For a version of this function that also deallocates chunks, see [`reset`].
768    ///
769    /// [`reset`]: Self::reset
770    ///
771    /// # Examples
772    ///
773    /// Basic usage:
774    ///
775    /// ```
776    /// # use bump_scope::Bump;
777    /// let mut scratch_allocator: Bump = Bump::new();
778    /// let items = [1, 2, 3];
779    ///
780    /// for item in items {
781    ///     // the scratch allocator is empty
782    ///     assert_eq!(scratch_allocator.stats().allocated(), 0);
783    ///
784    ///     // allocate on scratch allocator...
785    ///     let _ = scratch_allocator.alloc_fmt(format_args!("hello {item}"));
786    ///
787    ///     // reset the scratch allocator for the next iteration
788    ///     scratch_allocator.reset_to_start();
789    /// }
790    /// ```
791    ///
792    /// Detailed behavior:
793    ///
794    /// ```
795    /// # use bump_scope::Bump;
796    /// let mut bump: Bump = Bump::with_size(512);
797    ///
798    /// // won't fit in the first chunk, will be allocated in another chunk
799    /// bump.alloc_uninit_slice::<u8>(600);
800    ///
801    /// let chunks = bump.stats().small_to_big().collect::<Vec<_>>();
802    /// assert_eq!(chunks.len(), 2);
803    /// assert!(chunks[0].size() < chunks[1].size());
804    /// assert_eq!(chunks[0].allocated(), 0);
805    /// assert_eq!(chunks[1].allocated(), 600);
806    ///
807    /// bump.reset_to_start();
808    ///
809    /// // we still have two chunks...
810    /// assert_eq!(bump.stats().count(), 2);
811    ///
812    /// // ... but everything is deallocated
813    /// assert_eq!(bump.stats().allocated(), 0);
814    ///
815    /// // we are back at the first chunk
816    /// assert!(bump.stats().current_chunk().unwrap().prev().is_none());
817    /// ```
818    #[inline(always)]
819    pub fn reset_to_start(&mut self) {
820        self.raw.reset_to_start();
821    }
822
823    /// Returns a type which provides statistics about the memory usage of the bump allocator.
824    #[must_use]
825    #[inline(always)]
826    pub fn stats(&self) -> Stats<'_, A, S> {
827        self.as_scope().stats()
828    }
829
830    /// Returns this `&Bump` as a `&BumpScope`.
831    #[must_use]
832    #[inline(always)]
833    pub fn as_scope(&self) -> &BumpScope<'_, A, S> {
834        unsafe { transmute_ref(self) }
835    }
836
837    /// Returns this `&mut Bump` as a `&mut BumpScope`.
838    #[must_use]
839    #[inline(always)]
840    pub fn as_mut_scope(&mut self) -> &mut BumpScope<'_, A, S> {
841        unsafe { transmute_mut(self) }
842    }
843
844    /// Converts this `Bump` into a `Bump` with new settings.
845    ///
846    /// This function will fail to compile if:
847    /// - `NewS::UP != S::UP`
848    ///
849    /// # Panics
850    /// Panics if `!NewS::CLAIMABLE` and the bump allocator is currently [claimed].
851    ///
852    /// Panics if `NewS::GUARANTEED_ALLOCATED` and no chunk has been allocated.
853    ///
854    /// [claimed]: crate::traits::BumpAllocatorScope::claim
855    #[inline]
856    pub fn with_settings<NewS>(self) -> Bump<A, NewS>
857    where
858        A: BaseAllocator<NewS::GuaranteedAllocated>,
859        NewS: BumpAllocatorSettings,
860    {
861        self.raw.ensure_satisfies_settings::<NewS>();
862        unsafe { transmute_value(self) }
863    }
864
865    /// Borrows this `Bump` with new settings.
866    ///
867    /// This function will fail to compile if:
868    /// - `NewS::MIN_ALIGN != S::MIN_ALIGN`
869    /// - `NewS::UP != S::UP`
870    /// - `NewS::CLAIMABLE != S::CLAIMABLE`
871    /// - `NewS::GUARANTEED_ALLOCATED > S::GUARANTEED_ALLOCATED`
872    #[inline]
873    pub fn borrow_with_settings<NewS>(&self) -> &Bump<A, NewS>
874    where
875        A: BaseAllocator<NewS::GuaranteedAllocated>,
876        NewS: BumpAllocatorSettings,
877    {
878        self.raw.ensure_satisfies_settings_for_borrow::<NewS>();
879        unsafe { transmute_ref(self) }
880    }
881
882    /// Borrows this `Bump` mutably with new settings.
883    ///
884    /// This function will fail to compile if:
885    /// - `NewS::MIN_ALIGN < S::MIN_ALIGN`
886    /// - `NewS::UP != S::UP`
887    /// - `NewS::GUARANTEED_ALLOCATED != S::GUARANTEED_ALLOCATED`
888    /// - `NewS::CLAIMABLE != S::CLAIMABLE`
889    #[inline]
890    pub fn borrow_mut_with_settings<NewS>(&mut self) -> &mut Bump<A, NewS>
891    where
892        A: BaseAllocator<NewS::GuaranteedAllocated>,
893        NewS: BumpAllocatorSettings,
894    {
895        self.raw.ensure_satisfies_settings_for_borrow_mut::<NewS>();
896        unsafe { transmute_mut(self) }
897    }
898
899    /// Converts this `Bump` into a raw pointer.
900    ///
901    /// ```
902    /// # use bump_scope::Bump;
903    /// #
904    /// let bump: Bump = Bump::new();
905    /// bump.alloc_str("Hello, ");
906    ///
907    /// let ptr = bump.into_raw();
908    /// let bump: Bump = unsafe { Bump::from_raw(ptr) };
909    ///
910    /// bump.alloc_str("World!");
911    /// # assert_eq!(bump.stats().allocated(), 13);
912    /// ```
913    #[inline]
914    #[must_use]
915    pub fn into_raw(self) -> NonNull<()> {
916        ManuallyDrop::new(self).raw.clone().into_raw()
917    }
918
919    /// Converts the raw pointer that was created with [`into_raw`](Bump::into_raw) back into a `Bump`.
920    ///
921    /// # Safety
922    /// - `ptr` must come from a call to `Self::into_raw`.
923    /// - This function must only be called once with this `ptr`.
924    /// - The settings must match the original ones.
925    #[inline]
926    #[must_use]
927    pub unsafe fn from_raw(ptr: NonNull<()>) -> Self {
928        Self {
929            raw: unsafe { RawBump::from_raw(ptr) },
930        }
931    }
932}
933
934impl<'b, A, S> From<&'b Bump<A, S>> for &'b BumpScope<'b, A, S>
935where
936    A: BaseAllocator<S::GuaranteedAllocated>,
937    S: BumpAllocatorSettings,
938{
939    #[inline(always)]
940    fn from(value: &'b Bump<A, S>) -> Self {
941        value.as_scope()
942    }
943}
944
945impl<'b, A, S> From<&'b mut Bump<A, S>> for &'b mut BumpScope<'b, A, S>
946where
947    A: BaseAllocator<S::GuaranteedAllocated>,
948    S: BumpAllocatorSettings,
949{
950    #[inline(always)]
951    fn from(value: &'b mut Bump<A, S>) -> Self {
952        value.as_mut_scope()
953    }
954}
955
956/// Methods that forward to traits.
957// Documentation is in the forwarded to methods.
958#[allow(clippy::missing_errors_doc, clippy::missing_safety_doc)]
959impl<A, S> Bump<A, S>
960where
961    A: BaseAllocator<S::GuaranteedAllocated>,
962    S: BumpAllocatorSettings,
963{
964    traits::forward_methods! {
965        self: self
966        access: {self.as_scope()}
967        access_mut: {self.as_mut_scope()}
968        lifetime: '_
969    }
970}
971
972/// Additional `alloc` methods that are not available in traits.
973impl<A, S> Bump<A, S>
974where
975    A: BaseAllocator<S::GuaranteedAllocated>,
976    S: BumpAllocatorSettings,
977{
978    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
979    ///
980    /// This can be more performant than allocating `T` after the fact, as `Result<T, E>` may be constructed in the bump allocators memory instead of on the stack and then copied over.
981    ///
982    /// There is also [`alloc_try_with_mut`](Self::alloc_try_with_mut), optimized for a mutable reference.
983    ///
984    /// # Panics
985    /// Panics if the allocation fails.
986    ///
987    /// # Examples
988    #[cfg_attr(feature = "nightly-tests", doc = "```")]
989    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
990    /// # #![feature(offset_of_enum)]
991    /// # use core::mem::offset_of;
992    /// # use bump_scope::Bump;
993    /// # let bump: Bump = Bump::new();
994    /// let result = bump.alloc_try_with(|| -> Result<i32, i32> { Ok(123) });
995    /// assert_eq!(result.unwrap(), 123);
996    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
997    /// ```
998    #[cfg_attr(feature = "nightly-tests", doc = "```")]
999    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
1000    /// # use bump_scope::Bump;
1001    /// # let bump: Bump = Bump::new();
1002    /// let result = bump.alloc_try_with(|| -> Result<i32, i32> { Err(123) });
1003    /// assert_eq!(result.unwrap_err(), 123);
1004    /// assert_eq!(bump.stats().allocated(), 0);
1005    /// ```
1006    #[inline(always)]
1007    #[cfg(feature = "panic-on-alloc")]
1008    #[expect(clippy::missing_errors_doc)]
1009    pub fn alloc_try_with<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<BumpBox<'_, T>, E> {
1010        self.as_scope().alloc_try_with(f)
1011    }
1012
1013    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
1014    ///
1015    /// This can be more performant than allocating `T` after the fact, as `Result<T, E>` may be constructed in the bump allocators memory instead of on the stack and then copied over.
1016    ///
1017    /// There is also [`try_alloc_try_with_mut`](Self::try_alloc_try_with_mut), optimized for a mutable reference.
1018    ///
1019    /// # Errors
1020    /// Errors if the allocation fails.
1021    ///
1022    /// # Examples
1023    #[cfg_attr(feature = "nightly-tests", doc = "```")]
1024    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
1025    /// # #![feature(offset_of_enum)]
1026    /// # use core::mem::offset_of;
1027    /// # use bump_scope::Bump;
1028    /// # let bump: Bump = Bump::new();
1029    /// let result = bump.try_alloc_try_with(|| -> Result<i32, i32> { Ok(123) })?;
1030    /// assert_eq!(result.unwrap(), 123);
1031    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
1032    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1033    /// ```
1034    #[cfg_attr(feature = "nightly-tests", doc = "```")]
1035    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
1036    /// # use bump_scope::Bump;
1037    /// # let bump: Bump = Bump::new();
1038    /// let result = bump.try_alloc_try_with(|| -> Result<i32, i32> { Err(123) })?;
1039    /// assert_eq!(result.unwrap_err(), 123);
1040    /// assert_eq!(bump.stats().allocated(), 0);
1041    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1042    /// ```
1043    #[inline(always)]
1044    pub fn try_alloc_try_with<T, E>(
1045        &self,
1046        f: impl FnOnce() -> Result<T, E>,
1047    ) -> Result<Result<BumpBox<'_, T>, E>, AllocError> {
1048        self.as_scope().try_alloc_try_with(f)
1049    }
1050
1051    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
1052    ///
1053    /// This can be more performant than allocating `T` after the fact, as `Result<T, E>` may be constructed in the bump allocators memory instead of on the stack and then copied over.
1054    ///
1055    /// This is just like [`alloc_try_with`](Self::alloc_try_with), but optimized for a mutable reference.
1056    ///
1057    /// # Panics
1058    /// Panics if the allocation fails.
1059    ///
1060    /// # Examples
1061    #[cfg_attr(feature = "nightly-tests", doc = "```")]
1062    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
1063    /// # #![feature(offset_of_enum)]
1064    /// # use core::mem::offset_of;
1065    /// # use bump_scope::Bump;
1066    /// # let mut bump: Bump = Bump::new();
1067    /// let result = bump.alloc_try_with_mut(|| -> Result<i32, i32> { Ok(123) });
1068    /// assert_eq!(result.unwrap(), 123);
1069    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
1070    /// ```
1071    #[cfg_attr(feature = "nightly-tests", doc = "```")]
1072    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
1073    /// # use bump_scope::Bump;
1074    /// # let mut bump: Bump = Bump::new();
1075    /// let result = bump.alloc_try_with_mut(|| -> Result<i32, i32> { Err(123) });
1076    /// assert_eq!(result.unwrap_err(), 123);
1077    /// assert_eq!(bump.stats().allocated(), 0);
1078    /// ```
1079    #[inline(always)]
1080    #[cfg(feature = "panic-on-alloc")]
1081    #[expect(clippy::missing_errors_doc)]
1082    pub fn alloc_try_with_mut<T, E>(&mut self, f: impl FnOnce() -> Result<T, E>) -> Result<BumpBox<'_, T>, E> {
1083        self.as_mut_scope().alloc_try_with_mut(f)
1084    }
1085
1086    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
1087    ///
1088    /// This can be more performant than allocating `T` after the fact, as `Result<T, E>` may be constructed in the bump allocators memory instead of on the stack and then copied over.
1089    ///
1090    /// This is just like [`try_alloc_try_with`](Self::try_alloc_try_with), but optimized for a mutable reference.
1091    ///
1092    /// # Errors
1093    /// Errors if the allocation fails.
1094    ///
1095    /// # Examples
1096    #[cfg_attr(feature = "nightly-tests", doc = "```")]
1097    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
1098    /// # #![feature(offset_of_enum)]
1099    /// # use core::mem::offset_of;
1100    /// # use bump_scope::Bump;
1101    /// # let mut bump: Bump = Bump::new();
1102    /// let result = bump.try_alloc_try_with_mut(|| -> Result<i32, i32> { Ok(123) })?;
1103    /// assert_eq!(result.unwrap(), 123);
1104    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
1105    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1106    /// ```
1107    #[cfg_attr(feature = "nightly-tests", doc = "```")]
1108    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
1109    /// # use bump_scope::Bump;
1110    /// # let mut bump: Bump = Bump::new();
1111    /// let result = bump.try_alloc_try_with_mut(|| -> Result<i32, i32> { Err(123) })?;
1112    /// assert_eq!(result.unwrap_err(), 123);
1113    /// assert_eq!(bump.stats().allocated(), 0);
1114    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1115    /// ```
1116    #[inline(always)]
1117    pub fn try_alloc_try_with_mut<T, E>(
1118        &mut self,
1119        f: impl FnOnce() -> Result<T, E>,
1120    ) -> Result<Result<BumpBox<'_, T>, E>, AllocError> {
1121        self.as_mut_scope().try_alloc_try_with_mut(f)
1122    }
1123}
1124
1125unsafe impl<A, S> Allocator for Bump<A, S>
1126where
1127    A: BaseAllocator<S::GuaranteedAllocated>,
1128    S: BumpAllocatorSettings,
1129{
1130    #[inline(always)]
1131    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
1132        allocator_impl::allocate(&self.raw, layout)
1133    }
1134
1135    #[inline(always)]
1136    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
1137        unsafe { allocator_impl::deallocate(&self.raw, ptr, layout) };
1138    }
1139
1140    #[inline(always)]
1141    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
1142        unsafe { allocator_impl::grow(&self.raw, ptr, old_layout, new_layout) }
1143    }
1144
1145    #[inline(always)]
1146    unsafe fn grow_zeroed(
1147        &self,
1148        ptr: NonNull<u8>,
1149        old_layout: Layout,
1150        new_layout: Layout,
1151    ) -> Result<NonNull<[u8]>, AllocError> {
1152        unsafe { allocator_impl::grow_zeroed(&self.raw, ptr, old_layout, new_layout) }
1153    }
1154
1155    #[inline(always)]
1156    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
1157        unsafe { allocator_impl::shrink(&self.raw, ptr, old_layout, new_layout) }
1158    }
1159}