bump_scope/
bump_scope.rs

1use core::{
2    alloc::Layout,
3    cell::Cell,
4    ffi::CStr,
5    fmt::{self, Debug},
6    marker::PhantomData,
7    mem::{ManuallyDrop, MaybeUninit, transmute},
8    num::NonZeroUsize,
9    ops::Range,
10    panic::{RefUnwindSafe, UnwindSafe},
11    ptr::{self, NonNull},
12};
13
14#[cfg(feature = "nightly-clone-to-uninit")]
15use core::clone::CloneToUninit;
16
17use crate::{
18    BaseAllocator, Bump, BumpBox, BumpScopeGuard, BumpString, BumpVec, Checkpoint, ErrorBehavior, FixedBumpString,
19    FixedBumpVec, MinimumAlignment, MutBumpString, MutBumpVec, MutBumpVecRev, NoDrop, RawChunk, SizedTypeProperties,
20    SupportedMinimumAlignment, align_pos,
21    alloc::{AllocError, Allocator},
22    allocator_impl,
23    bump_align_guard::BumpAlignGuard,
24    chunk_header::ChunkHeader,
25    chunk_size::ChunkSize,
26    const_param_assert, down_align_usize,
27    layout::{ArrayLayout, CustomLayout, LayoutProps, SizedLayout},
28    maybe_default_allocator,
29    owned_slice::OwnedSlice,
30    polyfill::{non_null, transmute_mut, transmute_ref},
31    stats::{AnyStats, Stats},
32    up_align_usize_unchecked,
33};
34
35#[cfg(feature = "panic-on-alloc")]
36use crate::panic_on_error;
37
38macro_rules! make_type {
39    ($($allocator_parameter:tt)*) => {
40        /// A bump allocation scope.
41        ///
42        /// A `BumpScope`'s allocations are live for `'a`, which is the lifetime of its associated `BumpScopeGuard(Root)` or `scoped` closure.
43        ///
44        /// `BumpScope` has the same allocation api as `Bump`.
45        /// The only thing that is missing is [`reset`] and methods that consume the `Bump`.
46        /// For a method overview and examples, have a look at the [`Bump` docs][`Bump`].
47        ///
48        /// This type is provided as a parameter to the closure of [`Bump::scoped`], [`BumpScope::scoped`] or created
49        /// by [`BumpScopeGuard::scope`] and [`BumpScopeGuardRoot::scope`]. A [`Bump`] can also be turned into a `BumpScope` using
50        /// [`as_scope`], [`as_mut_scope`] or [`into`].
51        ///
52        /// [`Bump::scoped`]: crate::Bump::scoped
53        /// [`BumpScopeGuard::scope`]: crate::BumpScopeGuard::scope
54        /// [`BumpScopeGuardRoot::scope`]: crate::BumpScopeGuardRoot::scope
55        /// [`Bump`]: crate::Bump
56        /// [`scoped`]: Self::scoped
57        /// [`as_scope`]: crate::Bump::as_scope
58        /// [`as_mut_scope`]: crate::Bump::as_mut_scope
59        /// [`reset`]: crate::Bump::reset
60        /// [`into`]: crate::Bump#impl-From<%26Bump<A,+MIN_ALIGN,+UP,+GUARANTEED_ALLOCATED>>-for-%26BumpScope<'b,+A,+MIN_ALIGN,+UP,+GUARANTEED_ALLOCATED>
61        #[repr(transparent)]
62        pub struct BumpScope<
63            'a,
64            $($allocator_parameter)*,
65            const MIN_ALIGN: usize = 1,
66            const UP: bool = true,
67            const GUARANTEED_ALLOCATED: bool = true,
68            const DEALLOCATES: bool = true,
69        > {
70            pub(crate) chunk: Cell<RawChunk<A, UP, GUARANTEED_ALLOCATED>>,
71
72            /// Marks the lifetime of the mutably borrowed `BumpScopeGuard(Root)`.
73            marker: PhantomData<&'a ()>,
74        }
75    };
76}
77
78maybe_default_allocator!(make_type);
79
80impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> UnwindSafe
81    for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
82where
83    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
84    A: UnwindSafe,
85{
86}
87
88impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> RefUnwindSafe
89    for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
90where
91    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
92    A: UnwindSafe,
93{
94}
95
96impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Debug
97    for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
98where
99    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
100{
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        AnyStats::from(self.stats()).debug_format("BumpScope", f)
103    }
104}
105
106unsafe impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Allocator
107    for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
108where
109    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
110    A: BaseAllocator<GUARANTEED_ALLOCATED>,
111{
112    #[inline(always)]
113    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
114        allocator_impl::allocate(self, layout)
115    }
116
117    #[inline(always)]
118    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
119        unsafe { allocator_impl::deallocate(self, ptr, layout) };
120    }
121
122    #[inline(always)]
123    unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
124        unsafe { allocator_impl::grow(self, ptr, old_layout, new_layout) }
125    }
126
127    #[inline(always)]
128    unsafe fn grow_zeroed(
129        &self,
130        ptr: NonNull<u8>,
131        old_layout: Layout,
132        new_layout: Layout,
133    ) -> Result<NonNull<[u8]>, AllocError> {
134        unsafe { allocator_impl::grow_zeroed(self, ptr, old_layout, new_layout) }
135    }
136
137    #[inline(always)]
138    unsafe fn shrink(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
139        unsafe { allocator_impl::shrink(self, ptr, old_layout, new_layout) }
140    }
141}
142
143/// Methods for a [*guaranteed allocated*](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
144impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const DEALLOCATES: bool>
145    BumpScope<'a, A, MIN_ALIGN, UP, true, DEALLOCATES>
146where
147    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
148{
149    /// Returns a reference to the base allocator.
150    #[must_use]
151    #[inline(always)]
152    pub fn allocator(&self) -> &'a A {
153        self.stats().current_chunk().allocator()
154    }
155
156    /// Calls `f` with a new child scope.
157    ///
158    /// # Examples
159    ///
160    /// ```
161    /// # use bump_scope::Bump;
162    /// let mut bump: Bump = Bump::new();
163    ///
164    /// bump.scoped(|bump| {
165    ///     bump.alloc_str("Hello, world!");
166    ///     assert_eq!(bump.stats().allocated(), 13);
167    /// });
168    ///
169    /// assert_eq!(bump.stats().allocated(), 0);
170    /// ```
171    #[inline(always)]
172    pub fn scoped<R>(&mut self, f: impl FnOnce(BumpScope<A, MIN_ALIGN, UP, true, DEALLOCATES>) -> R) -> R {
173        let mut guard = self.scope_guard();
174        f(guard.scope())
175    }
176
177    /// Calls `f` with a new child scope of a new minimum alignment.
178    ///
179    /// # Examples
180    ///
181    #[cfg_attr(feature = "nightly-tests", doc = "```")]
182    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
183    /// # #![feature(pointer_is_aligned_to)]
184    /// # use bump_scope::Bump;
185    /// let mut bump: Bump = Bump::new();
186    ///
187    /// // bump starts off by being aligned to 16
188    /// assert!(bump.stats().current_chunk().bump_position().is_aligned_to(16));
189    ///
190    /// // allocate one byte
191    /// bump.alloc(1u8);
192    ///
193    /// // now the bump is only aligned to 1
194    /// // (if our `MIN_ALIGN` was higher, it would be that)
195    /// assert!(bump.stats().current_chunk().bump_position().addr().get() % 2 == 1);
196    /// assert_eq!(bump.stats().allocated(), 1);
197    ///
198    /// bump.scoped_aligned::<8, ()>(|bump| {
199    ///    // in here, the bump will have the specified minimum alignment of 8
200    ///    assert!(bump.stats().current_chunk().bump_position().is_aligned_to(8));
201    ///    assert_eq!(bump.stats().allocated(), 8);
202    ///
203    ///    // allocating a value with its size being a multiple of 8 will no longer have
204    ///    // to align the bump pointer before allocation
205    ///    bump.alloc(1u64);
206    ///    assert!(bump.stats().current_chunk().bump_position().is_aligned_to(8));
207    ///    assert_eq!(bump.stats().allocated(), 16);
208    ///    
209    ///    // allocating a value smaller than the minimum alignment must align the bump pointer
210    ///    // after the allocation, resulting in some wasted space
211    ///    bump.alloc(1u8);
212    ///    assert!(bump.stats().current_chunk().bump_position().is_aligned_to(8));
213    ///    assert_eq!(bump.stats().allocated(), 24);
214    /// });
215    ///
216    /// assert_eq!(bump.stats().allocated(), 1);
217    /// ```
218    #[inline(always)]
219    pub fn scoped_aligned<const NEW_MIN_ALIGN: usize, R>(
220        &mut self,
221        f: impl FnOnce(BumpScope<A, NEW_MIN_ALIGN, UP, true, DEALLOCATES>) -> R,
222    ) -> R
223    where
224        MinimumAlignment<NEW_MIN_ALIGN>: SupportedMinimumAlignment,
225    {
226        // This guard will reset the bump pointer to the current position, which is aligned to `MIN_ALIGN`.
227        let mut guard = self.scope_guard();
228        let scope = guard.scope();
229        scope.align::<NEW_MIN_ALIGN>();
230        f(unsafe { scope.cast_align() })
231    }
232
233    /// Calls `f` with this scope but with a new minimum alignment.
234    ///
235    /// # Examples
236    ///
237    /// Increase the minimum alignment:
238    #[cfg_attr(feature = "nightly-tests", doc = "```")]
239    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
240    /// # #![feature(pointer_is_aligned_to)]
241    /// # use bump_scope::Bump;
242    /// let mut bump: Bump = Bump::new();
243    /// let bump = bump.as_mut_scope();
244    ///
245    /// // here we're allocating with a `MIN_ALIGN` of `1`
246    /// let foo = bump.alloc_str("foo");
247    /// assert_eq!(bump.stats().allocated(), 3);
248    ///
249    /// let bar = bump.aligned::<8, _>(|bump| {
250    ///     // in here the bump position has been aligned to `8`
251    ///     assert_eq!(bump.stats().allocated(), 8);
252    ///     assert!(bump.stats().current_chunk().bump_position().is_aligned_to(8));
253    ///
254    ///     // make some allocations that benefit from the higher `MIN_ALIGN` of `8`
255    ///     let bar = bump.alloc(0u64);
256    ///     assert_eq!(bump.stats().allocated(), 16);
257    ///  
258    ///     // the bump position will stay aligned to `8`
259    ///     bump.alloc(0u8);
260    ///     assert_eq!(bump.stats().allocated(), 24);
261    ///
262    ///     bar
263    /// });
264    ///
265    /// assert_eq!(bump.stats().allocated(), 24);
266    ///
267    /// // continue making allocations with a `MIN_ALIGN` of `1`
268    /// let baz = bump.alloc_str("baz");
269    /// assert_eq!(bump.stats().allocated(), 24 + 3);
270    ///
271    /// dbg!(foo, bar, baz);
272    /// ```
273    ///
274    /// Decrease the minimum alignment:
275    #[cfg_attr(feature = "nightly-tests", doc = "```")]
276    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
277    /// # #![feature(pointer_is_aligned_to)]
278    /// # use bump_scope::{Bump, alloc::Global};
279    /// let mut bump: Bump<Global, 8> = Bump::new();
280    /// let bump = bump.as_mut_scope();
281    ///
282    /// // make some allocations that benefit from the `MIN_ALIGN` of `8`
283    /// let foo = bump.alloc(0u64);
284    ///
285    /// let bar = bump.aligned::<1, _>(|bump| {
286    ///     // make some allocations that benefit from the lower `MIN_ALIGN` of `1`
287    ///     let bar = bump.alloc(0u8);
288    ///
289    ///     // the bump position will not get aligned to `8` in here
290    ///     assert_eq!(bump.stats().allocated(), 8 + 1);
291    ///
292    ///     bar
293    /// });
294    ///
295    /// // after `aligned()`, the bump position will be aligned to `8` again
296    /// // to satisfy our `MIN_ALIGN`
297    /// assert!(bump.stats().current_chunk().bump_position().is_aligned_to(8));
298    /// assert_eq!(bump.stats().allocated(), 16);
299    ///
300    /// // continue making allocations that benefit from the `MIN_ALIGN` of `8`
301    /// let baz = bump.alloc(0u64);
302    ///
303    /// dbg!(foo, bar, baz);
304    /// ```
305    #[inline(always)]
306    pub fn aligned<const NEW_MIN_ALIGN: usize, R>(
307        &mut self,
308        f: impl FnOnce(BumpScope<'a, A, NEW_MIN_ALIGN, UP, true, DEALLOCATES>) -> R,
309    ) -> R
310    where
311        MinimumAlignment<NEW_MIN_ALIGN>: SupportedMinimumAlignment,
312    {
313        if NEW_MIN_ALIGN < MIN_ALIGN {
314            // This guard will align whatever the future bump position is back to `MIN_ALIGN`.
315            let guard = BumpAlignGuard::new(self);
316            f(unsafe { guard.scope.clone_unchecked().cast_align() })
317        } else {
318            self.align::<NEW_MIN_ALIGN>();
319            f(unsafe { self.clone_unchecked().cast_align() })
320        }
321    }
322
323    /// Creates a new [`BumpScopeGuard`].
324    ///
325    /// This allows for creation of child scopes.
326    ///
327    /// # Examples
328    ///
329    /// ```
330    /// # use bump_scope::Bump;
331    /// let mut bump: Bump = Bump::new();
332    ///
333    /// {
334    ///     let mut guard = bump.scope_guard();
335    ///     let bump = guard.scope();
336    ///     bump.alloc_str("Hello, world!");
337    ///     assert_eq!(bump.stats().allocated(), 13);
338    /// }
339    ///
340    /// assert_eq!(bump.stats().allocated(), 0);
341    /// ```
342    #[must_use]
343    #[inline(always)]
344    pub fn scope_guard(&mut self) -> BumpScopeGuard<'_, A, MIN_ALIGN, UP, DEALLOCATES> {
345        BumpScopeGuard::new(self)
346    }
347}
348
349/// Methods for a **not** [*guaranteed allocated*](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
350impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const DEALLOCATES: bool>
351    BumpScope<'a, A, MIN_ALIGN, UP, false, DEALLOCATES>
352where
353    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
354{
355    /// Returns a reference to the base allocator.
356    #[must_use]
357    #[inline(always)]
358    pub fn allocator(&self) -> Option<&'a A> {
359        self.stats().current_chunk().map(|c| c.allocator())
360    }
361}
362
363/// Methods that are always available.
364impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool>
365    BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
366where
367    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
368{
369    #[inline(always)]
370    pub(crate) unsafe fn new_unchecked(chunk: RawChunk<A, UP, GUARANTEED_ALLOCATED>) -> Self {
371        Self {
372            chunk: Cell::new(chunk),
373            marker: PhantomData,
374        }
375    }
376
377    /// Creates a checkpoint of the current bump position.
378    ///
379    /// The bump position can be reset to this checkpoint with [`reset_to`].
380    ///
381    /// [`reset_to`]: Self::reset_to
382    ///
383    /// # Examples
384    ///
385    /// ```
386    /// # use bump_scope::Bump;
387    /// let bump: Bump = Bump::new();
388    /// let checkpoint = bump.checkpoint();
389    ///
390    /// {
391    ///     let hello = bump.alloc_str("hello");
392    ///     assert_eq!(bump.stats().allocated(), 5);
393    ///     # _ = hello;
394    /// }
395    ///
396    /// unsafe { bump.reset_to(checkpoint); }
397    /// assert_eq!(bump.stats().allocated(), 0);
398    /// ```
399    #[inline]
400    pub fn checkpoint(&self) -> Checkpoint {
401        Checkpoint::new(self.chunk.get())
402    }
403
404    /// Resets the bump position to a previously created checkpoint.
405    /// The memory that has been allocated since then will be reused by future allocations.
406    ///
407    /// # Safety
408    ///
409    /// - the checkpoint must have been created by this bump allocator
410    /// - the bump allocator must not have been [`reset`] since creation of this checkpoint
411    /// - there must be no references to allocations made since creation of this checkpoint
412    /// - the checkpoint must not have been created by an`!GUARANTEED_ALLOCATED` when self is `GUARANTEED_ALLOCATED`
413    ///
414    /// [`reset`]: crate::Bump::reset
415    ///
416    /// # Examples
417    ///
418    /// ```
419    /// # use bump_scope::Bump;
420    /// let bump: Bump = Bump::new();
421    /// let checkpoint = bump.checkpoint();
422    ///
423    /// {
424    ///     let hello = bump.alloc_str("hello");
425    ///     assert_eq!(bump.stats().allocated(), 5);
426    ///     # _ = hello;
427    /// }
428    ///
429    /// unsafe { bump.reset_to(checkpoint); }
430    /// assert_eq!(bump.stats().allocated(), 0);
431    /// ```
432    #[inline]
433    #[expect(clippy::missing_panics_doc)] // just debug assertions
434    pub unsafe fn reset_to(&self, checkpoint: Checkpoint) {
435        // If the checkpoint was created when the bump allocator had no allocated chunk
436        // then the chunk pointer will point to the unallocated chunk header.
437        //
438        // In such cases we reset the bump pointer to the very start of the very first chunk.
439        //
440        // We don't check if the chunk pointer points to the unallocated chunk header
441        // if the bump allocator is `GUARANTEED_ALLOCATED`. We are allowed to not do this check
442        // because of this safety condition of `reset_to`:
443        // > the checkpoint must not have been created by an`!GUARANTEED_ALLOCATED` when self is `GUARANTEED_ALLOCATED`
444        if !GUARANTEED_ALLOCATED && checkpoint.chunk == ChunkHeader::UNALLOCATED {
445            if let Some(mut chunk) = self.chunk.get().guaranteed_allocated() {
446                while let Some(prev) = chunk.prev() {
447                    chunk = prev;
448                }
449
450                chunk.reset();
451                self.chunk.set(chunk.coerce_guaranteed_allocated());
452            }
453        } else {
454            debug_assert_ne!(
455                checkpoint.chunk,
456                ChunkHeader::UNALLOCATED,
457                "the safety conditions state that \"the checkpoint must not have been created by an`!GUARANTEED_ALLOCATED` when self is `GUARANTEED_ALLOCATED`\""
458            );
459
460            #[cfg(debug_assertions)]
461            {
462                let chunk = self
463                    .stats()
464                    .small_to_big()
465                    .find(|chunk| chunk.header() == checkpoint.chunk.cast())
466                    .expect("this checkpoint does not refer to any chunk of this bump allocator");
467
468                assert!(
469                    chunk.contains_addr_or_end(checkpoint.address.get()),
470                    "checkpoint address does not point within its chunk"
471                );
472            }
473
474            unsafe {
475                checkpoint.reset_within_chunk();
476                let chunk = RawChunk::from_header(checkpoint.chunk.cast());
477                self.chunk.set(chunk);
478            }
479        }
480    }
481
482    /// "Returns a type which provides statistics about the memory usage of the bump allocator.
483    #[must_use]
484    #[inline(always)]
485    pub fn stats(&self) -> Stats<'a, A, UP, GUARANTEED_ALLOCATED> {
486        self.chunk.get().stats()
487    }
488
489    #[inline(always)]
490    pub(crate) fn align<const ALIGN: usize>(&self)
491    where
492        MinimumAlignment<ALIGN>: SupportedMinimumAlignment,
493    {
494        if ALIGN > MIN_ALIGN {
495            // The UNALLOCATED chunk is always aligned.
496            if let Some(chunk) = self.chunk.get().guaranteed_allocated() {
497                let pos = chunk.pos().addr();
498                let addr = align_pos::<ALIGN, UP>(pos);
499                unsafe { chunk.set_pos_addr(addr) };
500            }
501        }
502    }
503
504    /// Converts this `BumpScope` into a ***not*** [guaranteed allocated](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
505    #[inline(always)]
506    pub fn into_not_guaranteed_allocated(self) -> BumpScope<'a, A, MIN_ALIGN, UP, false, DEALLOCATES> {
507        // SAFETY: it's always valid to interpret a guaranteed allocated as a non guaranteed allocated
508        unsafe { transmute(self) }
509    }
510
511    /// Borrows `BumpScope` as a ***not*** [guaranteed allocated](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
512    ///
513    /// Note that it's not possible to mutably borrow as a not guaranteed allocated bump allocator. That's because
514    /// a user could `mem::swap` it with an actual unallocated bump allocator which in turn would make `&mut self`
515    /// unallocated.
516    #[inline(always)]
517    pub fn as_not_guaranteed_allocated(&self) -> &BumpScope<'a, A, MIN_ALIGN, UP, false, DEALLOCATES> {
518        // SAFETY: it's always valid to interpret a guaranteed allocated as a non guaranteed allocated
519        unsafe { transmute_ref(self) }
520    }
521
522    /// # Safety
523    ///
524    /// - `self` must not be used until this clone is gone
525    #[inline(always)]
526    pub(crate) unsafe fn clone_unchecked(&self) -> BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES> {
527        unsafe { BumpScope::new_unchecked(self.chunk.get()) }
528    }
529
530    /// Converts this `BumpScope` into a raw pointer.
531    #[inline]
532    #[must_use]
533    pub fn into_raw(self) -> NonNull<()> {
534        let this = ManuallyDrop::new(self);
535        this.chunk.get().header().cast()
536    }
537
538    /// Converts the raw pointer that was created with [`into_raw`](Self::into_raw) back into a `BumpScope`.
539    ///
540    /// # Safety
541    /// This is highly unsafe, due to the number of invariants that aren't checked:
542    /// - `ptr` must have been created with `Self::into_raw`.
543    /// - This function must only be called once with this `ptr`.
544    /// - The lifetime must be the original one.
545    /// - Nothing must have been allocated since then.
546    #[inline]
547    #[must_use]
548    pub unsafe fn from_raw(ptr: NonNull<()>) -> Self {
549        Self {
550            chunk: Cell::new(unsafe { RawChunk::from_header(ptr.cast()) }),
551            marker: PhantomData,
552        }
553    }
554
555    #[inline(always)]
556    pub(crate) unsafe fn cast_align<const NEW_MIN_ALIGN: usize>(
557        self,
558    ) -> BumpScope<'a, A, NEW_MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
559    where
560        MinimumAlignment<NEW_MIN_ALIGN>: SupportedMinimumAlignment,
561    {
562        BumpScope {
563            chunk: self.chunk,
564            marker: PhantomData,
565        }
566    }
567
568    #[inline(always)]
569    pub(crate) unsafe fn cast_align_mut<const NEW_MIN_ALIGN: usize>(
570        &mut self,
571    ) -> &mut BumpScope<'a, A, NEW_MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
572    where
573        MinimumAlignment<NEW_MIN_ALIGN>: SupportedMinimumAlignment,
574    {
575        unsafe { &mut *ptr::from_mut(self).cast::<BumpScope<'a, A, NEW_MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>>() }
576    }
577
578    /// Will error at compile time if `NEW_MIN_ALIGN < MIN_ALIGN`.
579    #[inline(always)]
580    pub(crate) fn must_align_more<const NEW_MIN_ALIGN: usize>(&self)
581    where
582        MinimumAlignment<NEW_MIN_ALIGN>: SupportedMinimumAlignment,
583    {
584        const_param_assert! {
585            (const MIN_ALIGN: usize, const NEW_MIN_ALIGN: usize) => NEW_MIN_ALIGN >= MIN_ALIGN, "`into_aligned` or `as_mut_aligned` can't decrease the minimum alignment"
586        }
587
588        self.align::<NEW_MIN_ALIGN>();
589    }
590
591    /// Mutably borrows `BumpScope` with a new minimum alignment.
592    ///
593    /// **This cannot decrease the alignment.** Trying to decrease alignment will result in a compile error.
594    /// You can use [`aligned`](Self::aligned) or [`scoped_aligned`](Self::scoped_aligned) to decrease the alignment.
595    ///
596    /// When decreasing the alignment we need to make sure that the bump position is realigned to the original alignment.
597    /// That can only be ensured by having a function that takes a closure, like the methods mentioned above do.
598    #[inline(always)]
599    pub fn as_mut_aligned<const NEW_MIN_ALIGN: usize>(
600        &mut self,
601    ) -> &mut BumpScope<'a, A, NEW_MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
602    where
603        MinimumAlignment<NEW_MIN_ALIGN>: SupportedMinimumAlignment,
604    {
605        self.must_align_more::<NEW_MIN_ALIGN>();
606        unsafe { self.cast_align_mut() }
607    }
608
609    #[doc(hidden)]
610    #[inline(always)]
611    #[deprecated = "renamed to `as_mut_aligned`"]
612    pub fn as_aligned_mut<const NEW_MIN_ALIGN: usize>(
613        &mut self,
614    ) -> &mut BumpScope<'a, A, NEW_MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
615    where
616        MinimumAlignment<NEW_MIN_ALIGN>: SupportedMinimumAlignment,
617    {
618        self.as_mut_aligned()
619    }
620
621    /// Returns `&self` as is. This is useful for macros that support both `Bump` and `BumpScope`.
622    #[inline(always)]
623    pub fn as_scope(&self) -> &Self {
624        self
625    }
626
627    /// Returns `&mut self` as is. This is useful for macros that support both `Bump` and `BumpScope`.
628    #[inline(always)]
629    pub fn as_mut_scope(&mut self) -> &mut Self {
630        self
631    }
632
633    /// Converts this `BumpScope` into a `BumpScope` with a new minimum alignment.
634    ///
635    /// **This cannot decrease the alignment.** Trying to decrease alignment will result in a compile error.
636    /// You can use [`aligned`](Self::aligned) or [`scoped_aligned`](Self::scoped_aligned) to decrease the alignment.
637    ///
638    /// When decreasing the alignment we need to make sure that the bump position is realigned to the original alignment.
639    /// That can only be ensured by having a function that takes a closure, like the methods mentioned above do.
640    ///
641    /// If this was allowed to decrease the alignment it would break minimum alignment:
642    ///
643    /// ```ignore
644    /// # // We can't `compile_fail,E0080` this doc test because it does not do the compile step
645    /// # // that triggers the error.
646    /// # use bump_scope::{Bump, alloc::Global};
647    /// let mut bump: Bump<Global, 8, true> = Bump::new();
648    /// let mut guard = bump.scope_guard();
649    ///
650    /// {
651    ///     let scope = guard.scope().into_aligned::<1>();
652    ///     scope.alloc(0u8);
653    /// }
654    ///
655    /// {
656    ///     let scope = guard.scope();
657    ///     // scope is not aligned to `MIN_ALIGN`!!
658    /// }
659    ///
660    /// ```
661    #[inline(always)]
662    pub fn into_aligned<const NEW_MIN_ALIGN: usize>(
663        self,
664    ) -> BumpScope<'a, A, NEW_MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
665    where
666        MinimumAlignment<NEW_MIN_ALIGN>: SupportedMinimumAlignment,
667    {
668        self.must_align_more::<NEW_MIN_ALIGN>();
669        unsafe { self.cast_align() }
670    }
671
672    #[inline(always)]
673    pub(crate) unsafe fn use_prepared_slice_allocation<T>(&self, start: NonNull<T>, len: usize, cap: usize) -> NonNull<[T]> {
674        unsafe {
675            let end = start.add(len);
676
677            if UP {
678                self.set_aligned_pos(end.addr(), T::ALIGN);
679                NonNull::slice_from_raw_parts(start, len)
680            } else {
681                let dst_end = start.add(cap);
682                let dst = dst_end.sub(len);
683                start.copy_to(dst, len);
684                self.set_aligned_pos(dst.addr(), T::ALIGN);
685                NonNull::slice_from_raw_parts(dst, len)
686            }
687        }
688    }
689
690    #[inline(always)]
691    pub(crate) unsafe fn use_prepared_slice_allocation_rev<T>(
692        &self,
693        end: NonNull<T>,
694        len: usize,
695        cap: usize,
696    ) -> NonNull<[T]> {
697        unsafe {
698            if UP {
699                let dst = end.sub(cap);
700                let dst_end = dst.add(len);
701
702                let src = end.sub(len);
703
704                src.copy_to(dst, len);
705
706                self.set_aligned_pos(dst_end.addr(), T::ALIGN);
707                NonNull::slice_from_raw_parts(dst, len)
708            } else {
709                let dst = end.sub(len);
710                self.set_aligned_pos(dst.addr(), T::ALIGN);
711                NonNull::slice_from_raw_parts(dst, len)
712            }
713        }
714    }
715
716    /// Sets the bump position and aligns it to the required `MIN_ALIGN`.
717    ///
718    /// This does nothing if the current chunk is the UNALLOCATED one.
719    #[inline(always)]
720    pub(crate) unsafe fn set_pos(&self, pos: NonZeroUsize) {
721        unsafe {
722            let addr = align_pos::<MIN_ALIGN, UP>(pos);
723
724            if let Some(chunk) = self.chunk.get().guaranteed_allocated() {
725                chunk.set_pos_addr(addr);
726            }
727        }
728    }
729
730    /// A version of [`set_pos`](Self::set_pos) that only aligns the pointer
731    /// if it the `pos_align` is smaller than the `MIN_ALIGN`.
732    ///
733    /// This should only be called when the `pos_align` is statically known so
734    /// the branch gets optimized out.
735    ///
736    /// This does nothing if the current chunk is the UNALLOCATED one.
737    #[inline(always)]
738    pub(crate) unsafe fn set_aligned_pos(&self, pos: NonZeroUsize, pos_align: usize) {
739        debug_assert_eq!(pos.get() % pos_align, 0);
740
741        let addr = if pos_align < MIN_ALIGN {
742            align_pos::<MIN_ALIGN, UP>(pos)
743        } else {
744            pos.get()
745        };
746
747        if let Some(chunk) = self.chunk.get().guaranteed_allocated() {
748            unsafe { chunk.set_pos_addr(addr) };
749        }
750    }
751
752    /// Turns off deallocation and shrinking.
753    pub fn into_without_dealloc(self) -> BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, false> {
754        unsafe { transmute(self) }
755    }
756
757    /// Turns off deallocation and shrinking.
758    pub fn as_without_dealloc(&self) -> &BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, false> {
759        unsafe { transmute_ref(self) }
760    }
761
762    /// Turns off deallocation and shrinking.
763    pub fn as_mut_without_dealloc(&mut self) -> &mut BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, false> {
764        unsafe { transmute_mut(self) }
765    }
766
767    /// Turns on deallocation and shrinking.
768    pub fn into_with_dealloc(self) -> BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, true> {
769        unsafe { transmute(self) }
770    }
771
772    /// Turns on deallocation and shrinking.
773    pub fn as_with_dealloc(&self) -> &BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, true> {
774        unsafe { transmute_ref(self) }
775    }
776
777    /// Turns on deallocation and shrinking.
778    pub fn as_mut_with_dealloc(&mut self) -> &mut BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, true> {
779        unsafe { transmute_mut(self) }
780    }
781}
782
783/// Methods that are always available. (but with `A: Allocator`)
784impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool>
785    BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
786where
787    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
788    A: Allocator,
789{
790    /// Converts this `BumpScope` into a [guaranteed allocated](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
791    ///
792    /// See [`Bump::into_guaranteed_allocated`].
793    ///
794    /// # Panics
795    ///
796    /// Panics if the closure panics.
797    #[inline(always)]
798    #[cfg(feature = "panic-on-alloc")]
799    pub fn into_guaranteed_allocated(
800        self,
801        f: impl FnOnce() -> Bump<A, MIN_ALIGN, UP, true, DEALLOCATES>,
802    ) -> BumpScope<'a, A, MIN_ALIGN, UP, true, DEALLOCATES> {
803        self.ensure_allocated(f);
804        unsafe { transmute(self) }
805    }
806
807    /// Converts this `BumpScope` into a [guaranteed allocated](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
808    ///
809    /// See [`Bump::try_into_guaranteed_allocated`].
810    ///
811    /// # Errors
812    ///
813    /// Errors if the closure fails.
814    #[inline(always)]
815    pub fn try_into_guaranteed_allocated(
816        self,
817        f: impl FnOnce() -> Result<Bump<A, MIN_ALIGN, UP, true, DEALLOCATES>, AllocError>,
818    ) -> Result<BumpScope<'a, A, MIN_ALIGN, UP, true, DEALLOCATES>, AllocError> {
819        self.try_ensure_allocated(f)?;
820        Ok(unsafe { transmute(self) })
821    }
822
823    /// Borrows `BumpScope` as a [guaranteed allocated](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
824    ///
825    /// See [`Bump::as_guaranteed_allocated`].
826    ///
827    /// # Panics
828    ///
829    /// Panics if the closure panics.
830    #[inline(always)]
831    #[cfg(feature = "panic-on-alloc")]
832    pub fn as_guaranteed_allocated(
833        &self,
834        f: impl FnOnce() -> Bump<A, MIN_ALIGN, UP, true, DEALLOCATES>,
835    ) -> &BumpScope<'a, A, MIN_ALIGN, UP, true, DEALLOCATES> {
836        self.ensure_allocated(f);
837        unsafe { transmute_ref(self) }
838    }
839
840    /// Borrows `BumpScope` as a [guaranteed allocated](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
841    ///
842    /// See [`Bump::try_as_guaranteed_allocated`].
843    ///
844    /// # Errors
845    ///
846    /// Errors if the closure fails.
847    #[inline(always)]
848    pub fn try_as_guaranteed_allocated(
849        &self,
850        f: impl FnOnce() -> Result<Bump<A, MIN_ALIGN, UP, true, DEALLOCATES>, AllocError>,
851    ) -> Result<&BumpScope<'a, A, MIN_ALIGN, UP, true, DEALLOCATES>, AllocError> {
852        self.try_ensure_allocated(f)?;
853        Ok(unsafe { transmute_ref(self) })
854    }
855
856    /// Mutably borrows `BumpScope` as a [guaranteed allocated](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
857    ///
858    /// See [`Bump::as_mut_guaranteed_allocated`].
859    ///
860    /// # Panics
861    ///
862    /// Panics if the closure panics.
863    #[inline(always)]
864    #[cfg(feature = "panic-on-alloc")]
865    pub fn as_mut_guaranteed_allocated(
866        &mut self,
867        f: impl FnOnce() -> Bump<A, MIN_ALIGN, UP, true, DEALLOCATES>,
868    ) -> &mut BumpScope<'a, A, MIN_ALIGN, UP, true, DEALLOCATES> {
869        self.ensure_allocated(f);
870        unsafe { transmute_mut(self) }
871    }
872
873    /// Mutably borrows `BumpScope` as a [guaranteed allocated](crate#what-does-guaranteed-allocated-mean) `BumpScope`.
874    ///
875    /// See [`Bump::try_as_mut_guaranteed_allocated`].
876    ///
877    /// # Errors
878    ///
879    /// Errors if the closure fails.
880    #[inline(always)]
881    pub fn try_as_mut_guaranteed_allocated(
882        &mut self,
883        f: impl FnOnce() -> Result<Bump<A, MIN_ALIGN, UP, true, DEALLOCATES>, AllocError>,
884    ) -> Result<&mut BumpScope<'a, A, MIN_ALIGN, UP, true, DEALLOCATES>, AllocError> {
885        self.try_ensure_allocated(f)?;
886        Ok(unsafe { transmute_mut(self) })
887    }
888
889    #[inline(always)]
890    #[cfg(feature = "panic-on-alloc")]
891    pub(crate) fn ensure_allocated(&self, f: impl FnOnce() -> Bump<A, MIN_ALIGN, UP, true, DEALLOCATES>) {
892        if self.chunk.get().is_unallocated() {
893            unsafe {
894                self.chunk.set(RawChunk::from_header(f().into_raw().cast()));
895            }
896        }
897    }
898
899    #[inline(always)]
900    pub(crate) fn try_ensure_allocated(
901        &self,
902        f: impl FnOnce() -> Result<Bump<A, MIN_ALIGN, UP, true, DEALLOCATES>, AllocError>,
903    ) -> Result<(), AllocError> {
904        if self.chunk.get().is_unallocated() {
905            unsafe {
906                self.chunk.set(RawChunk::from_header(f()?.into_raw().cast()));
907            }
908        }
909
910        Ok(())
911    }
912}
913
914impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool>
915    BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
916where
917    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
918    A: BaseAllocator<GUARANTEED_ALLOCATED>,
919{
920    #[inline(always)]
921    pub(crate) fn generic_prepare_allocation<B: ErrorBehavior, T>(&self) -> Result<NonNull<T>, B> {
922        match self
923            .chunk
924            .get()
925            .prepare_allocation(MinimumAlignment::<MIN_ALIGN>, SizedLayout::new::<T>())
926        {
927            Some(ptr) => Ok(ptr.cast()),
928            None => match self.prepare_allocation_in_another_chunk::<B, T>() {
929                Ok(ptr) => Ok(ptr.cast()),
930                Err(err) => Err(err),
931            },
932        }
933    }
934
935    #[cold]
936    #[inline(never)]
937    pub(crate) fn prepare_allocation_in_another_chunk<E: ErrorBehavior, T>(&self) -> Result<NonNull<u8>, E>
938    where
939        MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
940    {
941        let layout = CustomLayout(Layout::new::<T>());
942
943        unsafe {
944            self.in_another_chunk(layout, |chunk, layout| {
945                chunk.prepare_allocation(MinimumAlignment::<MIN_ALIGN>, layout)
946            })
947        }
948    }
949
950    pub(crate) fn generic_prepare_slice_allocation<B: ErrorBehavior, T>(&self, min_cap: usize) -> Result<NonNull<[T]>, B> {
951        let range = self.prepare_allocation_range::<B, T>(min_cap)?;
952
953        // NB: We can't use `offset_from_unsigned`, because the size is not a multiple of `T`'s.
954        let cap = unsafe { non_null::byte_offset_from_unsigned(range.end, range.start) } / T::SIZE;
955
956        let ptr = if UP { range.start } else { unsafe { range.end.sub(cap) } };
957
958        Ok(NonNull::slice_from_raw_parts(ptr, cap))
959    }
960
961    /// Returns a pointer range.
962    /// The start and end pointers are aligned.
963    /// But `end - start` is *not* a multiple of `size_of::<T>()`.
964    /// So `end.offset_from_unsigned(start)` may not be used!
965    #[inline(always)]
966    pub(crate) fn prepare_allocation_range<B: ErrorBehavior, T>(&self, cap: usize) -> Result<Range<NonNull<T>>, B> {
967        let Ok(layout) = ArrayLayout::array::<T>(cap) else {
968            return Err(B::capacity_overflow());
969        };
970
971        let range = match self
972            .chunk
973            .get()
974            .prepare_allocation_range(MinimumAlignment::<MIN_ALIGN>, layout)
975        {
976            Some(ptr) => ptr,
977            None => self.prepare_allocation_range_in_another_chunk(layout)?,
978        };
979
980        Ok(range.start.cast::<T>()..range.end.cast::<T>())
981    }
982
983    #[cold]
984    #[inline(never)]
985    pub(crate) fn prepare_allocation_range_in_another_chunk<E: ErrorBehavior>(
986        &self,
987        layout: ArrayLayout,
988    ) -> Result<Range<NonNull<u8>>, E> {
989        unsafe {
990            self.in_another_chunk(layout, |chunk, layout| {
991                chunk.prepare_allocation_range(MinimumAlignment::<MIN_ALIGN>, layout)
992            })
993        }
994    }
995
996    #[inline(always)]
997    pub(crate) fn alloc_in_current_chunk(&self, layout: Layout) -> Option<NonNull<u8>> {
998        self.chunk.get().alloc(MinimumAlignment::<MIN_ALIGN>, CustomLayout(layout))
999    }
1000
1001    /// Allocation slow path.
1002    /// The active chunk must *not* have space for `layout`.
1003    #[cold]
1004    #[inline(never)]
1005    pub(crate) fn alloc_in_another_chunk<E: ErrorBehavior>(&self, layout: Layout) -> Result<NonNull<u8>, E> {
1006        unsafe {
1007            self.in_another_chunk(CustomLayout(layout), |chunk, layout| {
1008                chunk.alloc(MinimumAlignment::<MIN_ALIGN>, layout)
1009            })
1010        }
1011    }
1012
1013    #[inline(always)]
1014    pub(crate) fn do_alloc_sized<E: ErrorBehavior, T>(&self) -> Result<NonNull<T>, E> {
1015        match self.chunk.get().alloc(MinimumAlignment::<MIN_ALIGN>, SizedLayout::new::<T>()) {
1016            Some(ptr) => Ok(ptr.cast()),
1017            None => match self.do_alloc_sized_in_another_chunk::<E, T>() {
1018                Ok(ptr) => Ok(ptr.cast()),
1019                Err(err) => Err(err),
1020            },
1021        }
1022    }
1023
1024    #[cold]
1025    #[inline(never)]
1026    pub(crate) fn do_alloc_sized_in_another_chunk<E: ErrorBehavior, T>(&self) -> Result<NonNull<u8>, E>
1027    where
1028        MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
1029    {
1030        self.alloc_in_another_chunk(Layout::new::<T>())
1031    }
1032
1033    #[inline(always)]
1034    pub(crate) fn do_alloc_slice<E: ErrorBehavior, T>(&self, len: usize) -> Result<NonNull<T>, E> {
1035        let Ok(layout) = ArrayLayout::array::<T>(len) else {
1036            return Err(E::capacity_overflow());
1037        };
1038
1039        match self.chunk.get().alloc(MinimumAlignment::<MIN_ALIGN>, layout) {
1040            Some(ptr) => Ok(ptr.cast()),
1041            None => match self.do_alloc_slice_in_another_chunk::<E, T>(len) {
1042                Ok(ptr) => Ok(ptr.cast()),
1043                Err(err) => Err(err),
1044            },
1045        }
1046    }
1047
1048    #[inline(always)]
1049    pub(crate) fn do_alloc_slice_for<E: ErrorBehavior, T>(&self, value: &[T]) -> Result<NonNull<T>, E> {
1050        let layout = ArrayLayout::for_value(value);
1051
1052        match self.chunk.get().alloc(MinimumAlignment::<MIN_ALIGN>, layout) {
1053            Some(ptr) => Ok(ptr.cast()),
1054            None => match self.do_alloc_slice_in_another_chunk::<E, T>(value.len()) {
1055                Ok(ptr) => Ok(ptr.cast()),
1056                Err(err) => Err(err),
1057            },
1058        }
1059    }
1060
1061    #[cold]
1062    #[inline(never)]
1063    pub(crate) fn do_alloc_slice_in_another_chunk<E: ErrorBehavior, T>(&self, len: usize) -> Result<NonNull<u8>, E>
1064    where
1065        MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
1066    {
1067        let Ok(layout) = Layout::array::<T>(len) else {
1068            return Err(E::capacity_overflow());
1069        };
1070
1071        self.alloc_in_another_chunk(layout)
1072    }
1073
1074    /// # Safety
1075    ///
1076    /// `f` on the new chunk created by `RawChunk::append_for` with the layout `layout` must return `Some`.
1077    #[inline(always)]
1078    pub(crate) unsafe fn in_another_chunk<B: ErrorBehavior, R, L: LayoutProps>(
1079        &self,
1080        layout: L,
1081        mut f: impl FnMut(RawChunk<A, UP, true>, L) -> Option<R>,
1082    ) -> Result<R, B> {
1083        unsafe {
1084            let new_chunk: RawChunk<A, UP, true> = if let Some(mut chunk) = self.chunk.get().guaranteed_allocated() {
1085                while let Some(next_chunk) = chunk.next() {
1086                    chunk = next_chunk;
1087
1088                    // We don't reset the chunk position when we leave a scope, so we need to do it here.
1089                    chunk.reset();
1090
1091                    self.chunk.set(chunk.coerce_guaranteed_allocated());
1092
1093                    if let Some(ptr) = f(chunk, layout) {
1094                        return Ok(ptr);
1095                    }
1096                }
1097
1098                // there is no chunk that fits, we need a new chunk
1099                chunk.append_for(*layout)
1100            } else {
1101                // When this bump allocator is unallocated, `A` is guaranteed to implement `Default`,
1102                // `default_or_panic` will not panic.
1103                let allocator = A::default_or_panic();
1104
1105                RawChunk::new_in(
1106                    ChunkSize::from_capacity(*layout).ok_or_else(B::capacity_overflow)?,
1107                    None,
1108                    allocator,
1109                )
1110            }?;
1111
1112            self.chunk.set(new_chunk.coerce_guaranteed_allocated());
1113
1114            match f(new_chunk, layout) {
1115                Some(ptr) => Ok(ptr),
1116                _ => {
1117                    // SAFETY: We just appended a chunk for that specific layout, it must have enough space.
1118                    // We don't panic here so we don't produce any panic code when using `try_` apis.
1119                    // We check for that in `test-fallibility`.
1120                    core::hint::unreachable_unchecked()
1121                }
1122            }
1123        }
1124    }
1125}
1126
1127impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> NoDrop
1128    for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
1129{
1130}
1131
1132/// Methods to allocate. Available as fallible or infallible.
1133impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool>
1134    BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
1135where
1136    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
1137    A: BaseAllocator<GUARANTEED_ALLOCATED>,
1138{
1139    /// Allocate an object.
1140    ///
1141    /// # Panics
1142    /// Panics if the allocation fails.
1143    ///
1144    /// # Examples
1145    /// ```
1146    /// # use bump_scope::Bump;
1147    /// # let bump: Bump = Bump::new();
1148    /// let allocated = bump.alloc(123);
1149    /// assert_eq!(allocated, 123);
1150    /// ```
1151    #[inline(always)]
1152    #[cfg(feature = "panic-on-alloc")]
1153    pub fn alloc<T>(&self, value: T) -> BumpBox<'a, T> {
1154        panic_on_error(self.generic_alloc(value))
1155    }
1156
1157    /// Allocate an object.
1158    ///
1159    /// # Errors
1160    /// Errors if the allocation fails.
1161    ///
1162    /// # Examples
1163    /// ```
1164    /// # use bump_scope::Bump;
1165    /// # let bump: Bump = Bump::try_new()?;
1166    /// let allocated = bump.try_alloc(123)?;
1167    /// assert_eq!(allocated, 123);
1168    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1169    /// ```
1170    #[inline(always)]
1171    pub fn try_alloc<T>(&self, value: T) -> Result<BumpBox<'a, T>, AllocError> {
1172        self.generic_alloc(value)
1173    }
1174
1175    #[inline(always)]
1176    pub(crate) fn generic_alloc<B: ErrorBehavior, T>(&self, value: T) -> Result<BumpBox<'a, T>, B> {
1177        self.generic_alloc_with(|| value)
1178    }
1179
1180    /// Allocates space for an object, then calls `f` to produce the
1181    /// value to be put in that place.
1182    ///
1183    /// In some cases this could be more performant than `alloc(f())` because it
1184    /// permits the compiler to directly place `T` in the allocated memory instead of
1185    /// constructing it on the stack and copying it over.
1186    ///
1187    /// # Panics
1188    /// Panics if the allocation fails.
1189    ///
1190    /// # Examples
1191    /// ```
1192    /// # use bump_scope::Bump;
1193    /// # let bump: Bump = Bump::new();
1194    /// let allocated = bump.alloc_with(|| 123);
1195    /// assert_eq!(allocated, 123);
1196    /// ```
1197    #[inline(always)]
1198    #[cfg(feature = "panic-on-alloc")]
1199    pub fn alloc_with<T>(&self, f: impl FnOnce() -> T) -> BumpBox<'a, T> {
1200        panic_on_error(self.generic_alloc_with(f))
1201    }
1202
1203    /// Allocates space for an object, then calls `f` to produce the
1204    /// value to be put in that place.
1205    ///
1206    /// In some cases this could be more performant than `try_alloc(f())` because it
1207    /// permits the compiler to directly place `T` in the allocated memory instead of
1208    /// constructing it on the stack and copying it over.
1209    ///
1210    /// # Errors
1211    /// Errors if the allocation fails.
1212    ///
1213    /// # Examples
1214    /// ```
1215    /// # use bump_scope::Bump;
1216    /// # let bump: Bump = Bump::try_new()?;
1217    /// let allocated = bump.try_alloc_with(|| 123)?;
1218    /// assert_eq!(allocated, 123);
1219    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1220    /// ```
1221    #[inline(always)]
1222    pub fn try_alloc_with<T>(&self, f: impl FnOnce() -> T) -> Result<BumpBox<'a, T>, AllocError> {
1223        self.generic_alloc_with(f)
1224    }
1225
1226    #[inline(always)]
1227    pub(crate) fn generic_alloc_with<B: ErrorBehavior, T>(&self, f: impl FnOnce() -> T) -> Result<BumpBox<'a, T>, B> {
1228        Ok(self.generic_alloc_uninit()?.init(f()))
1229    }
1230
1231    /// Allocate an object with its default value.
1232    ///
1233    /// This is equivalent to <code>[alloc_with](Self::alloc_with)(T::default)</code>.
1234    ///
1235    /// # Panics
1236    /// Panics if the allocation fails.
1237    ///
1238    /// # Examples
1239    /// ```
1240    /// # use bump_scope::Bump;
1241    /// # let bump: Bump = Bump::new();
1242    /// let allocated = bump.alloc_default::<i32>();
1243    /// assert_eq!(allocated, 0);
1244    /// ```
1245    #[inline(always)]
1246    #[cfg(feature = "panic-on-alloc")]
1247    pub fn alloc_default<T: Default>(&self) -> BumpBox<'a, T> {
1248        panic_on_error(self.generic_alloc_default())
1249    }
1250
1251    /// Allocate an object with its default value.
1252    ///
1253    /// This is equivalent to <code>[try_alloc_with](Self::try_alloc_with)(T::default)</code>.
1254    ///
1255    /// # Errors
1256    /// Errors if the allocation fails.
1257    ///
1258    /// # Examples
1259    /// ```
1260    /// # use bump_scope::Bump;
1261    /// # let bump: Bump = Bump::try_new()?;
1262    /// let allocated = bump.try_alloc_default()?;
1263    /// assert_eq!(allocated, 0);
1264    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1265    /// ```
1266    #[inline(always)]
1267    pub fn try_alloc_default<T: Default>(&self) -> Result<BumpBox<'a, T>, AllocError> {
1268        self.generic_alloc_default()
1269    }
1270
1271    #[inline(always)]
1272    pub(crate) fn generic_alloc_default<B: ErrorBehavior, T: Default>(&self) -> Result<BumpBox<'a, T>, B> {
1273        self.generic_alloc_with(Default::default)
1274    }
1275
1276    /// Allocate an object by cloning it.
1277    ///
1278    /// Unlike `alloc(value.clone())` this method also works for dynamically-sized types.
1279    ///
1280    /// # Panics
1281    /// Panics if the allocation fails.
1282    ///
1283    /// # Examples
1284    ///
1285    /// Allocate a `slice`, `str`, `CStr`, `Path`:
1286    #[cfg_attr(feature = "nightly-clone-to-uninit", doc = "```")]
1287    #[cfg_attr(not(feature = "nightly-clone-to-uninit"), doc = "```ignore")]
1288    /// #![feature(clone_to_uninit)]
1289    ///
1290    /// use std::path::Path;
1291    /// # use bump_scope::Bump;
1292    /// # let bump: Bump = Bump::new();
1293    ///
1294    /// let cloned = bump.alloc_clone(&[1, 2, 3]);
1295    /// assert_eq!(cloned, &[1, 2, 3]);
1296    ///
1297    /// let cloned = bump.alloc_clone("foo");
1298    /// assert_eq!(cloned, "foo");
1299    ///
1300    /// let cloned = bump.alloc_clone(c"foo");
1301    /// assert_eq!(cloned, c"foo");
1302    ///
1303    /// let cloned = bump.alloc_clone(Path::new("foo"));
1304    /// assert_eq!(cloned, Path::new("foo"));
1305    /// ```
1306    ///
1307    /// Allocate a trait object:
1308    #[cfg_attr(feature = "nightly-clone-to-uninit", doc = "```")]
1309    #[cfg_attr(not(feature = "nightly-clone-to-uninit"), doc = "```ignore")]
1310    /// #![feature(clone_to_uninit)]
1311    ///
1312    /// use core::clone::CloneToUninit;
1313    /// # use bump_scope::Bump;
1314    ///
1315    /// trait FnClone: Fn() -> String + CloneToUninit {}
1316    /// impl<T: ?Sized + Fn() -> String + CloneToUninit> FnClone for T {}
1317    ///
1318    /// // the closure references a local variable
1319    /// let reference = &String::from("Hello,");
1320    ///
1321    /// // and owns a string that it will have to clone
1322    /// let value = String::from("world!");
1323    ///
1324    /// let closure = move || format!("{reference} {value}");
1325    /// let object: &dyn FnClone = &closure;
1326    ///
1327    /// assert_eq!(object(), "Hello, world!");
1328    ///
1329    /// let bump: Bump = Bump::new();
1330    /// let object_clone = bump.alloc_clone(object);
1331    ///
1332    /// assert_eq!(object_clone(), "Hello, world!");
1333    /// ```
1334    #[cfg(feature = "nightly-clone-to-uninit")]
1335    pub fn alloc_clone<T: CloneToUninit + ?Sized>(&self, value: &T) -> BumpBox<'a, T> {
1336        panic_on_error(self.generic_alloc_clone(value))
1337    }
1338
1339    /// Allocate an object by cloning it.
1340    ///
1341    /// Unlike `alloc(value.clone())` this method also works for dynamically-sized types.
1342    ///
1343    /// # Errors
1344    /// Errors if the allocation fails.
1345    ///
1346    /// # Examples
1347    ///
1348    /// Allocate a `slice`, `str`, `CStr`, `Path`:
1349    #[cfg_attr(feature = "nightly-clone-to-uninit", doc = "```")]
1350    #[cfg_attr(not(feature = "nightly-clone-to-uninit"), doc = "```ignore")]
1351    /// #![feature(clone_to_uninit)]
1352    ///
1353    /// use std::path::Path;
1354    /// # use bump_scope::Bump;
1355    /// # let bump: Bump = Bump::try_new()?;
1356    ///
1357    /// let cloned = bump.try_alloc_clone(&[1, 2, 3])?;
1358    /// assert_eq!(cloned, &[1, 2, 3]);
1359    ///
1360    /// let cloned = bump.try_alloc_clone("foo")?;
1361    /// assert_eq!(cloned, "foo");
1362    ///
1363    /// let cloned = bump.try_alloc_clone(c"foo")?;
1364    /// assert_eq!(cloned, c"foo");
1365    ///
1366    /// let cloned = bump.try_alloc_clone(Path::new("foo"))?;
1367    /// assert_eq!(cloned, Path::new("foo"));
1368    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1369    /// ```
1370    ///
1371    /// Allocate a trait object:
1372    #[cfg_attr(feature = "nightly-clone-to-uninit", doc = "```")]
1373    #[cfg_attr(not(feature = "nightly-clone-to-uninit"), doc = "```ignore")]
1374    /// #![feature(clone_to_uninit)]
1375    ///
1376    /// use core::clone::CloneToUninit;
1377    /// # use bump_scope::Bump;
1378    ///
1379    /// trait FnClone: Fn() -> String + CloneToUninit {}
1380    /// impl<T: ?Sized + Fn() -> String + CloneToUninit> FnClone for T {}
1381    ///
1382    /// // the closure references a local variable
1383    /// let reference = &String::from("Hello,");
1384    ///
1385    /// // and owns a string that it will have to clone
1386    /// let value = String::from("world!");
1387    ///
1388    /// let closure = move || format!("{reference} {value}");
1389    /// let object: &dyn FnClone = &closure;
1390    ///
1391    /// assert_eq!(object(), "Hello, world!");
1392    ///
1393    /// let bump: Bump = Bump::try_new()?;
1394    /// let object_clone = bump.try_alloc_clone(object)?;
1395    ///
1396    /// assert_eq!(object_clone(), "Hello, world!");
1397    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1398    /// ```
1399    #[cfg(feature = "nightly-clone-to-uninit")]
1400    pub fn try_alloc_clone<T: CloneToUninit + ?Sized>(&self, value: &T) -> Result<BumpBox<'a, T>, AllocError> {
1401        self.generic_alloc_clone(value)
1402    }
1403
1404    #[cfg(feature = "nightly-clone-to-uninit")]
1405    pub(crate) fn generic_alloc_clone<B: ErrorBehavior, T: CloneToUninit + ?Sized>(
1406        &self,
1407        value: &T,
1408    ) -> Result<BumpBox<'a, T>, B> {
1409        let data = self.generic_alloc_layout(Layout::for_value(value))?;
1410        let metadata = ptr::metadata(value);
1411
1412        unsafe {
1413            value.clone_to_uninit(data.as_ptr());
1414            let ptr = ptr::from_raw_parts_mut(data.as_ptr(), metadata);
1415            let ptr = NonNull::new_unchecked(ptr);
1416            Ok(BumpBox::from_raw(ptr))
1417        }
1418    }
1419
1420    /// Allocate a slice and fill it by moving elements from an existing slice.
1421    ///
1422    /// # Panics
1423    /// Panics if the allocation fails.
1424    ///
1425    /// # Examples
1426    /// ```
1427    /// # use bump_scope::Bump;
1428    /// # let bump: Bump = Bump::new();
1429    /// // by value
1430    /// let a = bump.alloc_slice_move([1, 2]);
1431    /// let b = bump.alloc_slice_move(vec![3, 4]);
1432    /// let c = bump.alloc_slice_move(bump.alloc_iter(5..=6));
1433    ///
1434    /// // by mutable reference
1435    /// let mut other = vec![7, 8];
1436    /// let d = bump.alloc_slice_move(&mut other);
1437    /// assert!(other.is_empty());
1438    ///
1439    /// assert_eq!(a, [1, 2]);
1440    /// assert_eq!(b, [3, 4]);
1441    /// assert_eq!(c, [5, 6]);
1442    /// assert_eq!(d, [7, 8]);
1443    /// ```
1444    #[inline(always)]
1445    #[cfg(feature = "panic-on-alloc")]
1446    pub fn alloc_slice_move<T>(&self, slice: impl OwnedSlice<Item = T>) -> BumpBox<'a, [T]> {
1447        panic_on_error(self.generic_alloc_slice_move(slice))
1448    }
1449
1450    /// Allocate a slice and fill it by moving elements from an existing slice.
1451    ///
1452    /// # Errors
1453    /// Errors if the allocation fails.
1454    ///
1455    /// # Examples
1456    /// ```
1457    /// # use bump_scope::Bump;
1458    /// # let bump: Bump = Bump::try_new()?;
1459    /// // by value
1460    /// let a = bump.try_alloc_slice_move([1, 2])?;
1461    /// let b = bump.try_alloc_slice_move(vec![3, 4])?;
1462    /// let c = bump.try_alloc_slice_move(bump.alloc_iter(5..=6))?;
1463    ///
1464    /// // by mutable reference
1465    /// let mut other = vec![7, 8];
1466    /// let d = bump.try_alloc_slice_move(&mut other)?;
1467    /// assert!(other.is_empty());
1468    ///
1469    /// assert_eq!(a, [1, 2]);
1470    /// assert_eq!(b, [3, 4]);
1471    /// assert_eq!(c, [5, 6]);
1472    /// assert_eq!(d, [7, 8]);
1473    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1474    /// ```
1475    #[inline(always)]
1476    pub fn try_alloc_slice_move<T>(&self, slice: impl OwnedSlice<Item = T>) -> Result<BumpBox<'a, [T]>, AllocError> {
1477        self.generic_alloc_slice_move(slice)
1478    }
1479
1480    #[inline(always)]
1481    pub(crate) fn generic_alloc_slice_move<B: ErrorBehavior, T>(
1482        &self,
1483        slice: impl OwnedSlice<Item = T>,
1484    ) -> Result<BumpBox<'a, [T]>, B> {
1485        Ok(BumpVec::generic_from_owned_slice_in(slice, self)?.into_boxed_slice())
1486    }
1487
1488    /// Allocate a slice and fill it by `Copy`ing elements from an existing slice.
1489    ///
1490    /// # Panics
1491    /// Panics if the allocation fails.
1492    ///
1493    /// # Examples
1494    /// ```
1495    /// # use bump_scope::Bump;
1496    /// # let bump: Bump = Bump::new();
1497    /// let allocated = bump.alloc_slice_copy(&[1, 2, 3]);
1498    /// assert_eq!(allocated, [1, 2, 3]);
1499    /// ```
1500    #[inline(always)]
1501    #[cfg(feature = "panic-on-alloc")]
1502    pub fn alloc_slice_copy<T: Copy>(&self, slice: &[T]) -> BumpBox<'a, [T]> {
1503        panic_on_error(self.generic_alloc_slice_copy(slice))
1504    }
1505
1506    /// Allocate a slice and fill it by `Copy`ing elements from an existing slice.
1507    ///
1508    /// # Errors
1509    /// Errors if the allocation fails.
1510    ///
1511    /// # Examples
1512    /// ```
1513    /// # use bump_scope::Bump;
1514    /// # let bump: Bump = Bump::try_new()?;
1515    /// let allocated = bump.try_alloc_slice_copy(&[1, 2, 3])?;
1516    /// assert_eq!(allocated, [1, 2, 3]);
1517    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1518    /// ```
1519    #[inline(always)]
1520    pub fn try_alloc_slice_copy<T: Copy>(&self, slice: &[T]) -> Result<BumpBox<'a, [T]>, AllocError> {
1521        self.generic_alloc_slice_copy(slice)
1522    }
1523
1524    #[inline(always)]
1525    pub(crate) fn generic_alloc_slice_copy<B: ErrorBehavior, T: Copy>(&self, slice: &[T]) -> Result<BumpBox<'a, [T]>, B> {
1526        if T::IS_ZST {
1527            return Ok(BumpBox::zst_slice_clone(slice));
1528        }
1529
1530        let len = slice.len();
1531        let src = slice.as_ptr();
1532        let dst = self.do_alloc_slice_for(slice)?;
1533
1534        unsafe {
1535            core::ptr::copy_nonoverlapping(src, dst.as_ptr(), len);
1536            Ok(BumpBox::from_raw(NonNull::slice_from_raw_parts(dst, len)))
1537        }
1538    }
1539
1540    /// Allocate a slice and fill it by `Clone`ing elements from an existing slice.
1541    ///
1542    /// # Panics
1543    /// Panics if the allocation fails.
1544    ///
1545    /// # Examples
1546    /// ```
1547    /// # use bump_scope::Bump;
1548    /// # let bump: Bump = Bump::new();
1549    /// let allocated = bump.alloc_slice_clone(&[String::from("a"), String::from("b")]);
1550    /// assert_eq!(allocated, [String::from("a"), String::from("b")]);
1551    /// ```
1552    #[inline(always)]
1553    #[cfg(feature = "panic-on-alloc")]
1554    pub fn alloc_slice_clone<T: Clone>(&self, slice: &[T]) -> BumpBox<'a, [T]> {
1555        panic_on_error(self.generic_alloc_slice_clone(slice))
1556    }
1557
1558    /// Allocate a slice and fill it by `Clone`ing elements from an existing slice.
1559    ///
1560    /// # Errors
1561    /// Errors if the allocation fails.
1562    ///
1563    /// # Examples
1564    /// ```
1565    /// # use bump_scope::Bump;
1566    /// # let bump: Bump = Bump::try_new()?;
1567    /// let allocated = bump.try_alloc_slice_clone(&[String::from("a"), String::from("b")])?;
1568    /// assert_eq!(allocated, [String::from("a"), String::from("b")]);
1569    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1570    /// ```
1571    #[inline(always)]
1572    pub fn try_alloc_slice_clone<T: Clone>(&self, slice: &[T]) -> Result<BumpBox<'a, [T]>, AllocError> {
1573        self.generic_alloc_slice_clone(slice)
1574    }
1575
1576    #[inline(always)]
1577    pub(crate) fn generic_alloc_slice_clone<B: ErrorBehavior, T: Clone>(&self, slice: &[T]) -> Result<BumpBox<'a, [T]>, B> {
1578        if T::IS_ZST {
1579            return Ok(BumpBox::zst_slice_clone(slice));
1580        }
1581
1582        Ok(self.generic_alloc_uninit_slice_for(slice)?.init_clone(slice))
1583    }
1584
1585    /// Allocate a slice and fill it with elements by cloning `value`.
1586    ///
1587    /// # Panics
1588    /// Panics if the allocation fails.
1589    ///
1590    /// # Examples
1591    /// ```
1592    /// # use bump_scope::Bump;
1593    /// # let bump: Bump = Bump::new();
1594    /// let allocated = bump.alloc_slice_fill(3, "ho");
1595    /// assert_eq!(allocated, ["ho", "ho", "ho"]);
1596    /// ```
1597    #[inline(always)]
1598    #[cfg(feature = "panic-on-alloc")]
1599    pub fn alloc_slice_fill<T: Clone>(&self, len: usize, value: T) -> BumpBox<'a, [T]> {
1600        panic_on_error(self.generic_alloc_slice_fill(len, value))
1601    }
1602
1603    /// Allocate a slice and fill it with elements by cloning `value`.
1604    ///
1605    /// # Errors
1606    /// Errors if the allocation fails.
1607    ///
1608    /// # Examples
1609    /// ```
1610    /// # use bump_scope::Bump;
1611    /// # let bump: Bump = Bump::try_new()?;
1612    /// let allocated = bump.try_alloc_slice_fill(3, "ho")?;
1613    /// assert_eq!(allocated, ["ho", "ho", "ho"]);
1614    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1615    /// ```
1616    #[inline(always)]
1617    pub fn try_alloc_slice_fill<T: Clone>(&self, len: usize, value: T) -> Result<BumpBox<'a, [T]>, AllocError> {
1618        self.generic_alloc_slice_fill(len, value)
1619    }
1620
1621    #[inline(always)]
1622    pub(crate) fn generic_alloc_slice_fill<B: ErrorBehavior, T: Clone>(
1623        &self,
1624        len: usize,
1625        value: T,
1626    ) -> Result<BumpBox<'a, [T]>, B> {
1627        if T::IS_ZST {
1628            return Ok(BumpBox::zst_slice_fill(len, value));
1629        }
1630
1631        Ok(self.generic_alloc_uninit_slice(len)?.init_fill(value))
1632    }
1633
1634    /// Allocates a slice by fill it with elements returned by calling a closure repeatedly.
1635    ///
1636    /// This method uses a closure to create new values. If you'd rather
1637    /// [`Clone`] a given value, use [`alloc_slice_fill`](Self::alloc_slice_fill). If you want to use the [`Default`]
1638    /// trait to generate values, you can pass [`Default::default`] as the
1639    /// argument.
1640    ///
1641    /// # Panics
1642    /// Panics if the allocation fails.
1643    ///
1644    /// # Examples
1645    /// ```
1646    /// # use bump_scope::Bump;
1647    /// # let bump: Bump = Bump::new();
1648    /// let allocated = bump.alloc_slice_fill_with::<i32>(3, Default::default);
1649    /// assert_eq!(allocated, [0, 0, 0]);
1650    /// ```
1651    #[inline(always)]
1652    #[cfg(feature = "panic-on-alloc")]
1653    pub fn alloc_slice_fill_with<T>(&self, len: usize, f: impl FnMut() -> T) -> BumpBox<'a, [T]> {
1654        panic_on_error(self.generic_alloc_slice_fill_with(len, f))
1655    }
1656
1657    /// Allocates a slice by fill it with elements returned by calling a closure repeatedly.
1658    ///
1659    /// This method uses a closure to create new values. If you'd rather
1660    /// [`Clone`] a given value, use [`try_alloc_slice_fill`](Self::try_alloc_slice_fill). If you want to use the [`Default`]
1661    /// trait to generate values, you can pass [`Default::default`] as the
1662    /// argument.
1663    ///
1664    /// # Errors
1665    /// Errors if the allocation fails.
1666    ///
1667    /// # Examples
1668    /// ```
1669    /// # use bump_scope::Bump;
1670    /// # let bump: Bump = Bump::try_new()?;
1671    /// let allocated = bump.try_alloc_slice_fill_with::<i32>(3, Default::default)?;
1672    /// assert_eq!(allocated, [0, 0, 0]);
1673    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1674    /// ```
1675    #[inline(always)]
1676    pub fn try_alloc_slice_fill_with<T>(&self, len: usize, f: impl FnMut() -> T) -> Result<BumpBox<'a, [T]>, AllocError> {
1677        self.generic_alloc_slice_fill_with(len, f)
1678    }
1679
1680    #[inline(always)]
1681    pub(crate) fn generic_alloc_slice_fill_with<B: ErrorBehavior, T>(
1682        &self,
1683        len: usize,
1684        f: impl FnMut() -> T,
1685    ) -> Result<BumpBox<'a, [T]>, B> {
1686        if T::IS_ZST {
1687            return Ok(BumpBox::zst_slice_fill_with(len, f));
1688        }
1689
1690        Ok(self.generic_alloc_uninit_slice(len)?.init_fill_with(f))
1691    }
1692
1693    /// Allocate a `str`.
1694    ///
1695    /// # Panics
1696    /// Panics if the allocation fails.
1697    ///
1698    /// # Examples
1699    /// ```
1700    /// # use bump_scope::Bump;
1701    /// # let bump: Bump = Bump::new();
1702    /// let allocated = bump.alloc_str("Hello, world!");
1703    /// assert_eq!(allocated, "Hello, world!");
1704    /// ```
1705    #[inline(always)]
1706    #[cfg(feature = "panic-on-alloc")]
1707    pub fn alloc_str(&self, src: &str) -> BumpBox<'a, str> {
1708        panic_on_error(self.generic_alloc_str(src))
1709    }
1710
1711    /// Allocate a `str`.
1712    ///
1713    /// # Errors
1714    /// Errors if the allocation fails.
1715    ///
1716    /// # Examples
1717    /// ```
1718    /// # use bump_scope::Bump;
1719    /// # let bump: Bump = Bump::try_new()?;
1720    /// let allocated = bump.try_alloc_str("Hello, world!")?;
1721    /// assert_eq!(allocated, "Hello, world!");
1722    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1723    /// ```
1724    #[inline(always)]
1725    pub fn try_alloc_str(&self, src: &str) -> Result<BumpBox<'a, str>, AllocError> {
1726        self.generic_alloc_str(src)
1727    }
1728
1729    #[inline(always)]
1730    pub(crate) fn generic_alloc_str<B: ErrorBehavior>(&self, src: &str) -> Result<BumpBox<'a, str>, B> {
1731        let slice = self.generic_alloc_slice_copy(src.as_bytes())?;
1732
1733        // SAFETY: input is `str` so this is too
1734        Ok(unsafe { BumpBox::from_utf8_unchecked(slice) })
1735    }
1736
1737    /// Allocate a `str` from format arguments.
1738    ///
1739    /// If you have a `&mut self` you can use [`alloc_fmt_mut`](Self::alloc_fmt_mut)
1740    /// instead for better performance.
1741    ///
1742    /// # Panics
1743    /// Panics if the allocation fails.
1744    ///
1745    /// This technically also panics if the `fmt()` implementation returned an Error,
1746    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1747    /// that should be equivalent to an allocation failure.
1748    ///
1749    /// # Examples
1750    /// ```
1751    /// # use bump_scope::Bump;
1752    /// # let bump: Bump = Bump::new();
1753    /// let one = 1;
1754    /// let two = 2;
1755    /// let string = bump.alloc_fmt(format_args!("{one} + {two} = {}", one + two));
1756    ///
1757    /// assert_eq!(string, "1 + 2 = 3");
1758    /// ```
1759    #[inline(always)]
1760    #[cfg(feature = "panic-on-alloc")]
1761    pub fn alloc_fmt(&self, args: fmt::Arguments) -> BumpBox<'a, str> {
1762        panic_on_error(self.generic_alloc_fmt(args))
1763    }
1764
1765    /// Allocate a `str` from format arguments.
1766    ///
1767    /// If you have a `&mut self` you can use [`try_alloc_fmt_mut`](Self::try_alloc_fmt_mut)
1768    /// instead for better performance.
1769    ///
1770    /// # Errors
1771    /// Errors if the allocation fails.
1772    ///
1773    /// This technically also errors if the `fmt()` implementation returned an Error,
1774    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1775    /// that should be equivalent to an allocation failure.
1776    ///
1777    /// # Examples
1778    /// ```
1779    /// # use bump_scope::Bump;
1780    /// # let bump: Bump = Bump::try_new()?;
1781    /// let one = 1;
1782    /// let two = 2;
1783    /// let string = bump.try_alloc_fmt(format_args!("{one} + {two} = {}", one + two))?;
1784    ///
1785    /// assert_eq!(string, "1 + 2 = 3");
1786    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1787    /// ```
1788    #[inline(always)]
1789    pub fn try_alloc_fmt(&self, args: fmt::Arguments) -> Result<BumpBox<'a, str>, AllocError> {
1790        self.generic_alloc_fmt(args)
1791    }
1792
1793    #[inline(always)]
1794    pub(crate) fn generic_alloc_fmt<B: ErrorBehavior>(&self, args: fmt::Arguments) -> Result<BumpBox<'a, str>, B> {
1795        if let Some(string) = args.as_str() {
1796            return self.generic_alloc_str(string);
1797        }
1798
1799        let mut string = BumpString::new_in(self);
1800        string.generic_write_fmt(args)?;
1801        Ok(string.into_boxed_str())
1802    }
1803
1804    /// Allocate a `str` from format arguments.
1805    ///
1806    /// This function is designed as a performance improvement over [`alloc_fmt`](Self::alloc_fmt).
1807    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
1808    /// for the temporary string buffer used for the allocation. As a result, that string buffer rarely needs to grow.
1809    ///
1810    /// # Panics
1811    /// Panics if the allocation fails.
1812    ///
1813    /// This technically also panics if the `fmt()` implementation returned an Error,
1814    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1815    /// that should be equivalent to an allocation failure.
1816    ///
1817    /// # Examples
1818    /// ```
1819    /// # use bump_scope::Bump;
1820    /// # let mut bump: Bump = Bump::new();
1821    /// let one = 1;
1822    /// let two = 2;
1823    /// let string = bump.alloc_fmt_mut(format_args!("{one} + {two} = {}", one + two));
1824    ///
1825    /// assert_eq!(string, "1 + 2 = 3");
1826    /// ```
1827    #[inline(always)]
1828    #[cfg(feature = "panic-on-alloc")]
1829    pub fn alloc_fmt_mut(&mut self, args: fmt::Arguments) -> BumpBox<'a, str> {
1830        panic_on_error(self.generic_alloc_fmt_mut(args))
1831    }
1832
1833    /// Allocate a `str` from format arguments.
1834    ///
1835    /// This function is designed as a performance improvement over [`try_alloc_fmt`](Self::try_alloc_fmt).
1836    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
1837    /// for the temporary string buffer used for the allocation. As a result, that string buffer rarely needs to grow.
1838    ///
1839    /// # Errors
1840    /// Errors if the allocation fails.
1841    ///
1842    /// This technically also errors if the `fmt()` implementation returned an Error,
1843    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1844    /// that should be equivalent to an allocation failure.
1845    ///
1846    /// # Examples
1847    /// ```
1848    /// # use bump_scope::Bump;
1849    /// # let mut bump: Bump = Bump::try_new()?;
1850    /// let one = 1;
1851    /// let two = 2;
1852    /// let string = bump.try_alloc_fmt_mut(format_args!("{one} + {two} = {}", one + two))?;
1853    ///
1854    /// assert_eq!(string, "1 + 2 = 3");
1855    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1856    /// ```
1857    #[inline(always)]
1858    pub fn try_alloc_fmt_mut(&mut self, args: fmt::Arguments) -> Result<BumpBox<'a, str>, AllocError> {
1859        self.generic_alloc_fmt_mut(args)
1860    }
1861
1862    #[inline(always)]
1863    pub(crate) fn generic_alloc_fmt_mut<B: ErrorBehavior>(&mut self, args: fmt::Arguments) -> Result<BumpBox<'a, str>, B> {
1864        if let Some(string) = args.as_str() {
1865            return self.generic_alloc_str(string);
1866        }
1867
1868        let mut string = MutBumpString::new_in(self);
1869        string.generic_write_fmt(args)?;
1870        Ok(string.into_boxed_str())
1871    }
1872
1873    /// Allocate a `CStr`.
1874    ///
1875    /// # Panics
1876    /// Panics if the allocation fails.
1877    ///
1878    /// # Examples
1879    /// ```
1880    /// # use bump_scope::Bump;
1881    /// # let bump: Bump = Bump::new();
1882    /// let allocated = bump.alloc_cstr(c"Hello, world!");
1883    /// assert_eq!(allocated, c"Hello, world!");
1884    /// ```
1885    #[inline(always)]
1886    #[cfg(feature = "panic-on-alloc")]
1887    pub fn alloc_cstr(&self, src: &CStr) -> &'a CStr {
1888        panic_on_error(self.generic_alloc_cstr(src))
1889    }
1890
1891    /// Allocate a `CStr`.
1892    ///
1893    /// # Errors
1894    /// Errors if the allocation fails.
1895    ///
1896    /// # Examples
1897    /// ```
1898    /// # use bump_scope::Bump;
1899    /// # let bump: Bump = Bump::try_new()?;
1900    /// let allocated = bump.try_alloc_cstr(c"Hello, world!")?;
1901    /// assert_eq!(allocated, c"Hello, world!");
1902    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1903    /// ```
1904    #[inline(always)]
1905    pub fn try_alloc_cstr(&self, src: &CStr) -> Result<&'a CStr, AllocError> {
1906        self.generic_alloc_cstr(src)
1907    }
1908
1909    #[inline(always)]
1910    pub(crate) fn generic_alloc_cstr<B: ErrorBehavior>(&self, src: &CStr) -> Result<&'a CStr, B> {
1911        let slice = self.generic_alloc_slice_copy(src.to_bytes_with_nul())?.into_ref();
1912
1913        // SAFETY: input is `CStr` so this is too
1914        Ok(unsafe { CStr::from_bytes_with_nul_unchecked(slice) })
1915    }
1916
1917    /// Allocate a `CStr` from a `str`.
1918    ///
1919    /// If `src` contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1920    ///
1921    /// # Panics
1922    /// Panics if the allocation fails.
1923    ///
1924    /// # Examples
1925    /// ```
1926    /// # use bump_scope::Bump;
1927    /// # let bump: Bump = Bump::new();
1928    /// let allocated = bump.alloc_cstr_from_str("Hello, world!");
1929    /// assert_eq!(allocated, c"Hello, world!");
1930    ///
1931    /// let allocated = bump.alloc_cstr_from_str("abc\0def");
1932    /// assert_eq!(allocated, c"abc");
1933    /// ```
1934    #[inline(always)]
1935    #[cfg(feature = "panic-on-alloc")]
1936    pub fn alloc_cstr_from_str(&self, src: &str) -> &'a CStr {
1937        panic_on_error(self.generic_alloc_cstr_from_str(src))
1938    }
1939
1940    /// Allocate a `CStr` from a `str`.
1941    ///
1942    /// If `src` contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1943    ///
1944    /// # Errors
1945    /// Errors if the allocation fails.
1946    ///
1947    /// # Examples
1948    /// ```
1949    /// # use bump_scope::Bump;
1950    /// # let bump: Bump = Bump::try_new()?;
1951    /// let allocated = bump.try_alloc_cstr_from_str("Hello, world!")?;
1952    /// assert_eq!(allocated, c"Hello, world!");
1953    ///
1954    /// let allocated = bump.try_alloc_cstr_from_str("abc\0def")?;
1955    /// assert_eq!(allocated, c"abc");
1956    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1957    /// ```
1958    #[inline(always)]
1959    pub fn try_alloc_cstr_from_str(&self, src: &str) -> Result<&'a CStr, AllocError> {
1960        self.generic_alloc_cstr_from_str(src)
1961    }
1962
1963    #[inline(always)]
1964    pub(crate) fn generic_alloc_cstr_from_str<B: ErrorBehavior>(&self, src: &str) -> Result<&'a CStr, B> {
1965        let src = src.as_bytes();
1966
1967        if let Some(nul) = src.iter().position(|&c| c == b'\0') {
1968            let bytes_with_nul = unsafe { src.get_unchecked(..nul + 1) };
1969            let cstr = unsafe { CStr::from_bytes_with_nul_unchecked(bytes_with_nul) };
1970            self.generic_alloc_cstr(cstr)
1971        } else {
1972            // `src` contains no null
1973            let dst = self.do_alloc_slice(src.len() + 1)?;
1974
1975            unsafe {
1976                core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_ptr(), src.len());
1977                dst.as_ptr().add(src.len()).write(0);
1978
1979                let bytes = core::slice::from_raw_parts(dst.as_ptr(), src.len() + 1);
1980                Ok(CStr::from_bytes_with_nul_unchecked(bytes))
1981            }
1982        }
1983    }
1984
1985    /// Allocate a `CStr` from format arguments.
1986    ///
1987    /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1988    ///
1989    /// If you have a `&mut self` you can use [`alloc_cstr_fmt_mut`](Self::alloc_cstr_fmt_mut)
1990    /// instead for better performance.
1991    ///
1992    /// # Panics
1993    /// Panics if the allocation fails.
1994    ///
1995    /// This technically also panics if the `fmt()` implementation returned an Error,
1996    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1997    /// that should be equivalent to an allocation failure.
1998    ///
1999    /// # Examples
2000    /// ```
2001    /// # use bump_scope::Bump;
2002    /// # let bump: Bump = Bump::new();
2003    /// let one = 1;
2004    /// let two = 2;
2005    /// let string = bump.alloc_cstr_fmt(format_args!("{one} + {two} = {}", one + two));
2006    /// assert_eq!(string, c"1 + 2 = 3");
2007    ///
2008    /// let one = bump.alloc_cstr_fmt(format_args!("{one}\0{two}"));
2009    /// assert_eq!(one, c"1");
2010    /// ```
2011    #[inline(always)]
2012    #[cfg(feature = "panic-on-alloc")]
2013    pub fn alloc_cstr_fmt(&self, args: fmt::Arguments) -> &'a CStr {
2014        panic_on_error(self.generic_alloc_cstr_fmt(args))
2015    }
2016
2017    /// Allocate a `CStr` from format arguments.
2018    ///
2019    /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
2020    ///
2021    /// If you have a `&mut self` you can use [`try_alloc_cstr_fmt_mut`](Self::try_alloc_cstr_fmt_mut)
2022    /// instead for better performance.
2023    ///
2024    /// # Errors
2025    /// Errors if the allocation fails.
2026    ///
2027    /// This technically also errors if the `fmt()` implementation returned an Error,
2028    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
2029    /// that should be equivalent to an allocation failure.
2030    ///
2031    /// # Examples
2032    /// ```
2033    /// # use bump_scope::Bump;
2034    /// # let bump: Bump = Bump::try_new()?;
2035    /// let one = 1;
2036    /// let two = 2;
2037    /// let string = bump.try_alloc_cstr_fmt(format_args!("{one} + {two} = {}", one + two))?;
2038    /// assert_eq!(string, c"1 + 2 = 3");
2039    ///
2040    /// let one = bump.try_alloc_cstr_fmt(format_args!("{one}\0{two}"))?;
2041    /// assert_eq!(one, c"1");
2042    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2043    /// ```
2044    #[inline(always)]
2045    pub fn try_alloc_cstr_fmt(&self, args: fmt::Arguments) -> Result<&'a CStr, AllocError> {
2046        self.generic_alloc_cstr_fmt(args)
2047    }
2048
2049    #[inline(always)]
2050    pub(crate) fn generic_alloc_cstr_fmt<B: ErrorBehavior>(&self, args: fmt::Arguments) -> Result<&'a CStr, B> {
2051        if let Some(string) = args.as_str() {
2052            return self.generic_alloc_cstr_from_str(string);
2053        }
2054
2055        let mut string = BumpString::new_in(self);
2056        string.generic_write_fmt(args)?;
2057        string.generic_into_cstr()
2058    }
2059
2060    /// Allocate a `CStr` from format arguments.
2061    ///
2062    /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
2063    ///
2064    /// This function is designed as a performance improvement over [`alloc_cstr_fmt`](Self::alloc_cstr_fmt).
2065    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
2066    /// for the temporary string buffer used for the allocation. As a result, that string buffer rarely needs to grow.
2067    ///
2068    /// # Panics
2069    /// Panics if the allocation fails.
2070    ///
2071    /// This technically also panics if the `fmt()` implementation returned an Error,
2072    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
2073    /// that should be equivalent to an allocation failure.
2074    ///
2075    /// # Examples
2076    /// ```
2077    /// # use bump_scope::Bump;
2078    /// # let mut bump: Bump = Bump::new();
2079    /// let one = 1;
2080    /// let two = 2;
2081    /// let string = bump.alloc_cstr_fmt_mut(format_args!("{one} + {two} = {}", one + two));
2082    /// assert_eq!(string, c"1 + 2 = 3");
2083    ///
2084    /// let one = bump.alloc_cstr_fmt_mut(format_args!("{one}\0{two}"));
2085    /// assert_eq!(one, c"1");
2086    /// ```
2087    #[inline(always)]
2088    #[cfg(feature = "panic-on-alloc")]
2089    pub fn alloc_cstr_fmt_mut(&mut self, args: fmt::Arguments) -> &'a CStr {
2090        panic_on_error(self.generic_alloc_cstr_fmt_mut(args))
2091    }
2092
2093    /// Allocate a `CStr` from format arguments.
2094    ///
2095    /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
2096    ///
2097    /// This function is designed as a performance improvement over [`try_alloc_cstr_fmt`](Self::try_alloc_cstr_fmt).
2098    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
2099    /// for the temporary string buffer used for the allocation. As a result, that string buffer rarely needs to grow.
2100    ///
2101    /// # Errors
2102    /// Errors if the allocation fails.
2103    ///
2104    /// This technically also errors if the `fmt()` implementation returned an Error,
2105    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
2106    /// that should be equivalent to an allocation failure.
2107    ///
2108    /// # Examples
2109    /// ```
2110    /// # use bump_scope::Bump;
2111    /// # let mut bump: Bump = Bump::try_new()?;
2112    /// let one = 1;
2113    /// let two = 2;
2114    /// let string = bump.try_alloc_cstr_fmt_mut(format_args!("{one} + {two} = {}", one + two))?;
2115    /// assert_eq!(string, c"1 + 2 = 3");
2116    ///
2117    /// let one = bump.try_alloc_cstr_fmt_mut(format_args!("{one}\0{two}"))?;
2118    /// assert_eq!(one, c"1");
2119    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2120    /// ```
2121    #[inline(always)]
2122    pub fn try_alloc_cstr_fmt_mut(&mut self, args: fmt::Arguments) -> Result<&'a CStr, AllocError> {
2123        self.generic_alloc_cstr_fmt_mut(args)
2124    }
2125
2126    #[inline(always)]
2127    pub(crate) fn generic_alloc_cstr_fmt_mut<B: ErrorBehavior>(&mut self, args: fmt::Arguments) -> Result<&'a CStr, B> {
2128        if let Some(string) = args.as_str() {
2129            return self.generic_alloc_cstr_from_str(string);
2130        }
2131
2132        let mut string = MutBumpString::new_in(self);
2133        string.generic_write_fmt(args)?;
2134        string.generic_into_cstr()
2135    }
2136
2137    /// Allocate elements of an iterator into a slice.
2138    ///
2139    /// If you have an `impl ExactSizeIterator` then you can use [`alloc_iter_exact`] instead for better performance.
2140    ///
2141    /// If `iter` is not an `ExactSizeIterator` but you have a `&mut self` you can still get somewhat better performance by using [`alloc_iter_mut`].
2142    ///
2143    /// [`alloc_iter_exact`]: Self::alloc_iter_exact
2144    /// [`alloc_iter_mut`]: Self::alloc_iter_mut
2145    ///
2146    /// # Panics
2147    /// Panics if the allocation fails.
2148    ///
2149    /// # Examples
2150    /// ```
2151    /// # use bump_scope::Bump;
2152    /// # let bump: Bump = Bump::new();
2153    /// let slice = bump.alloc_iter([1, 2, 3]);
2154    /// assert_eq!(slice, [1, 2, 3]);
2155    /// ```
2156    #[inline(always)]
2157    #[cfg(feature = "panic-on-alloc")]
2158    pub fn alloc_iter<T>(&self, iter: impl IntoIterator<Item = T>) -> BumpBox<'a, [T]> {
2159        panic_on_error(self.generic_alloc_iter(iter))
2160    }
2161
2162    /// Allocate elements of an iterator into a slice.
2163    ///
2164    /// If you have an `impl ExactSizeIterator` then you can use [`try_alloc_iter_exact`] instead for better performance.
2165    ///
2166    /// If `iter` is not an `ExactSizeIterator` but you have a `&mut self` you can still get somewhat better performance by using [`try_alloc_iter_mut`].
2167    ///
2168    /// [`try_alloc_iter_exact`]: Self::try_alloc_iter_exact
2169    /// [`try_alloc_iter_mut`]: Self::try_alloc_iter_mut
2170    ///
2171    /// # Errors
2172    /// Errors if the allocation fails.
2173    ///
2174    /// # Examples
2175    /// ```
2176    /// # use bump_scope::Bump;
2177    /// # let bump: Bump = Bump::try_new()?;
2178    /// let slice = bump.try_alloc_iter([1, 2, 3])?;
2179    /// assert_eq!(slice, [1, 2, 3]);
2180    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2181    /// ```
2182    #[inline(always)]
2183    pub fn try_alloc_iter<T>(&self, iter: impl IntoIterator<Item = T>) -> Result<BumpBox<'a, [T]>, AllocError> {
2184        self.generic_alloc_iter(iter)
2185    }
2186
2187    #[inline(always)]
2188    pub(crate) fn generic_alloc_iter<B: ErrorBehavior, T>(
2189        &self,
2190        iter: impl IntoIterator<Item = T>,
2191    ) -> Result<BumpBox<'a, [T]>, B> {
2192        let iter = iter.into_iter();
2193        let capacity = iter.size_hint().0;
2194
2195        let mut vec = BumpVec::<T, &Self>::generic_with_capacity_in(capacity, self)?;
2196
2197        for value in iter {
2198            vec.generic_push(value)?;
2199        }
2200
2201        Ok(vec.into_boxed_slice())
2202    }
2203
2204    /// Allocate elements of an `ExactSizeIterator` into a slice.
2205    ///
2206    /// # Panics
2207    /// Panics if the allocation fails.
2208    ///
2209    /// # Examples
2210    /// ```
2211    /// # use bump_scope::Bump;
2212    /// # let bump: Bump = Bump::new();
2213    /// let slice = bump.alloc_iter_exact([1, 2, 3]);
2214    /// assert_eq!(slice, [1, 2, 3]);
2215    /// ```
2216    #[inline(always)]
2217    #[cfg(feature = "panic-on-alloc")]
2218    pub fn alloc_iter_exact<T, I>(&self, iter: impl IntoIterator<Item = T, IntoIter = I>) -> BumpBox<'a, [T]>
2219    where
2220        I: ExactSizeIterator<Item = T>,
2221    {
2222        panic_on_error(self.generic_alloc_iter_exact(iter))
2223    }
2224
2225    /// Allocate elements of an `ExactSizeIterator` into a slice.
2226    ///
2227    /// # Errors
2228    /// Errors if the allocation fails.
2229    ///
2230    /// # Examples
2231    /// ```
2232    /// # use bump_scope::Bump;
2233    /// # let bump: Bump = Bump::try_new()?;
2234    /// let slice = bump.try_alloc_iter_exact([1, 2, 3])?;
2235    /// assert_eq!(slice, [1, 2, 3]);
2236    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2237    /// ```
2238    #[inline(always)]
2239    pub fn try_alloc_iter_exact<T, I>(
2240        &self,
2241        iter: impl IntoIterator<Item = T, IntoIter = I>,
2242    ) -> Result<BumpBox<'a, [T]>, AllocError>
2243    where
2244        I: ExactSizeIterator<Item = T>,
2245    {
2246        self.generic_alloc_iter_exact(iter)
2247    }
2248
2249    #[inline(always)]
2250    pub(crate) fn generic_alloc_iter_exact<B: ErrorBehavior, T, I>(
2251        &self,
2252        iter: impl IntoIterator<Item = T, IntoIter = I>,
2253    ) -> Result<BumpBox<'a, [T]>, B>
2254    where
2255        I: ExactSizeIterator<Item = T>,
2256    {
2257        let mut iter = iter.into_iter();
2258        let len = iter.len();
2259
2260        let mut vec = BumpVec::<T, &Self>::generic_with_capacity_in(len, self)?;
2261
2262        while vec.len() != vec.capacity() {
2263            match iter.next() {
2264                // SAFETY: we checked above that `len != capacity`, so there is space
2265                Some(value) => unsafe { vec.push_unchecked(value) },
2266                None => break,
2267            }
2268        }
2269
2270        Ok(vec.into_fixed_vec().into_boxed_slice())
2271    }
2272
2273    /// Allocate elements of an iterator into a slice.
2274    ///
2275    /// This function is designed as a performance improvement over [`alloc_iter`](Self::alloc_iter).
2276    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
2277    /// for the temporary vector used for the allocation. As a result, that vector rarely needs to grow.
2278    ///
2279    /// When bumping downwards, prefer [`alloc_iter_mut_rev`](Self::alloc_iter_mut_rev) instead.
2280    ///
2281    /// # Panics
2282    /// Panics if the allocation fails.
2283    ///
2284    /// # Examples
2285    /// ```
2286    /// # use bump_scope::Bump;
2287    /// # let mut bump: Bump = Bump::new();
2288    /// let slice = bump.alloc_iter_mut([1, 2, 3]);
2289    /// assert_eq!(slice, [1, 2, 3]);
2290    /// ```
2291    #[inline(always)]
2292    #[cfg(feature = "panic-on-alloc")]
2293    pub fn alloc_iter_mut<T>(&mut self, iter: impl IntoIterator<Item = T>) -> BumpBox<'a, [T]> {
2294        panic_on_error(self.generic_alloc_iter_mut(iter))
2295    }
2296
2297    /// Allocate elements of an iterator into a slice.
2298    ///
2299    /// This function is designed as a performance improvement over [`try_alloc_iter`](Self::try_alloc_iter).
2300    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
2301    /// for the temporary vector used for the allocation. As a result, that vector rarely needs to grow.
2302    ///
2303    /// When bumping downwards, prefer [`alloc_iter_mut_rev`](Self::alloc_iter_mut_rev) instead.
2304    ///
2305    /// # Errors
2306    /// Errors if the allocation fails.
2307    ///
2308    /// # Examples
2309    /// ```
2310    /// # use bump_scope::Bump;
2311    /// # let mut bump: Bump = Bump::try_new()?;
2312    /// let slice = bump.try_alloc_iter_mut([1, 2, 3])?;
2313    /// assert_eq!(slice, [1, 2, 3]);
2314    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2315    /// ```
2316    #[inline(always)]
2317    pub fn try_alloc_iter_mut<T>(&mut self, iter: impl IntoIterator<Item = T>) -> Result<BumpBox<'a, [T]>, AllocError> {
2318        self.generic_alloc_iter_mut(iter)
2319    }
2320
2321    #[inline(always)]
2322    pub(crate) fn generic_alloc_iter_mut<B: ErrorBehavior, T>(
2323        &mut self,
2324        iter: impl IntoIterator<Item = T>,
2325    ) -> Result<BumpBox<'a, [T]>, B> {
2326        let iter = iter.into_iter();
2327        let capacity = iter.size_hint().0;
2328
2329        let mut vec = MutBumpVec::<T, &mut Self>::generic_with_capacity_in(capacity, self)?;
2330
2331        for value in iter {
2332            vec.generic_push(value)?;
2333        }
2334
2335        Ok(vec.into_boxed_slice())
2336    }
2337
2338    /// Allocate elements of an iterator into a slice in reverse order.
2339    ///
2340    /// Compared to [`alloc_iter_mut`] this function is more performant
2341    /// for downwards bumping allocators as the allocation for the vector can be shrunk in place
2342    /// without any `ptr::copy`.
2343    ///
2344    /// The reverse is true when upwards allocating. In that case it's better to use [`alloc_iter_mut`] to prevent
2345    /// the `ptr::copy`.
2346    ///
2347    /// [`alloc_iter_mut`]: Self::alloc_iter_mut
2348    ///
2349    /// # Panics
2350    /// Panics if the allocation fails.
2351    ///
2352    /// # Examples
2353    /// ```
2354    /// # use bump_scope::Bump;
2355    /// # let mut bump: Bump = Bump::new();
2356    /// let slice = bump.alloc_iter_mut_rev([1, 2, 3]);
2357    /// assert_eq!(slice, [3, 2, 1]);
2358    /// ```
2359    #[inline(always)]
2360    #[cfg(feature = "panic-on-alloc")]
2361    pub fn alloc_iter_mut_rev<T>(&mut self, iter: impl IntoIterator<Item = T>) -> BumpBox<'a, [T]> {
2362        panic_on_error(self.generic_alloc_iter_mut_rev(iter))
2363    }
2364
2365    /// Allocate elements of an iterator into a slice in reverse order.
2366    ///
2367    /// Compared to [`try_alloc_iter_mut`] this function is more performant
2368    /// for downwards bumping allocators as the allocation for the vector can be shrunk in place
2369    /// without any `ptr::copy`.
2370    ///
2371    /// The reverse is true when upwards allocating. In that case it's better to use [`try_alloc_iter_mut`] to prevent
2372    /// the `ptr::copy`.
2373    ///
2374    /// [`try_alloc_iter_mut`]: Self::try_alloc_iter_mut
2375    ///
2376    /// # Errors
2377    /// Errors if the allocation fails.
2378    ///
2379    /// # Examples
2380    /// ```
2381    /// # use bump_scope::Bump;
2382    /// # let mut bump: Bump = Bump::try_new()?;
2383    /// let slice = bump.try_alloc_iter_mut_rev([1, 2, 3])?;
2384    /// assert_eq!(slice, [3, 2, 1]);
2385    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2386    /// ```
2387    #[inline(always)]
2388    pub fn try_alloc_iter_mut_rev<T>(&mut self, iter: impl IntoIterator<Item = T>) -> Result<BumpBox<'a, [T]>, AllocError> {
2389        self.generic_alloc_iter_mut_rev(iter)
2390    }
2391
2392    #[inline(always)]
2393    pub(crate) fn generic_alloc_iter_mut_rev<B: ErrorBehavior, T>(
2394        &mut self,
2395        iter: impl IntoIterator<Item = T>,
2396    ) -> Result<BumpBox<'a, [T]>, B> {
2397        let iter = iter.into_iter();
2398        let capacity = iter.size_hint().0;
2399
2400        let mut vec = MutBumpVecRev::<T, &mut Self>::generic_with_capacity_in(capacity, self)?;
2401
2402        for value in iter {
2403            vec.generic_push(value)?;
2404        }
2405
2406        Ok(vec.into_boxed_slice())
2407    }
2408
2409    /// Allocate an unitialized object.
2410    ///
2411    /// You can safely initialize the object with [`init`](BumpBox::init) or unsafely with [`assume_init`](BumpBox::assume_init).
2412    ///
2413    /// # Panics
2414    /// Panics if the allocation fails.
2415    ///
2416    /// # Examples
2417    /// Safely:
2418    /// ```
2419    /// # use bump_scope::Bump;
2420    /// # let bump: Bump = Bump::new();
2421    /// let uninit = bump.alloc_uninit();
2422    ///
2423    /// let five = uninit.init(5);
2424    ///
2425    /// assert_eq!(*five, 5)
2426    /// ```
2427    ///
2428    /// Unsafely:
2429    /// ```
2430    /// # use bump_scope::Bump;
2431    /// # let bump: Bump = Bump::new();
2432    /// let mut uninit = bump.alloc_uninit();
2433    ///
2434    /// let five = unsafe {
2435    ///     uninit.write(5);
2436    ///     uninit.assume_init()
2437    /// };
2438    ///
2439    /// assert_eq!(*five, 5)
2440    /// ```
2441    #[inline(always)]
2442    #[cfg(feature = "panic-on-alloc")]
2443    pub fn alloc_uninit<T>(&self) -> BumpBox<'a, MaybeUninit<T>> {
2444        panic_on_error(self.generic_alloc_uninit())
2445    }
2446
2447    /// Allocate an unitialized object.
2448    ///
2449    /// You can safely initialize the object with [`init`](BumpBox::init) or unsafely with [`assume_init`](BumpBox::assume_init).
2450    ///
2451    /// # Errors
2452    /// Errors if the allocation fails.
2453    ///
2454    /// # Examples
2455    /// Safely:
2456    /// ```
2457    /// # use bump_scope::Bump;
2458    /// # let bump: Bump = Bump::new();
2459    /// let uninit = bump.try_alloc_uninit()?;
2460    ///
2461    /// let five = uninit.init(5);
2462    ///
2463    /// assert_eq!(*five, 5);
2464    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2465    /// ```
2466    ///
2467    /// Unsafely:
2468    /// ```
2469    /// # use bump_scope::Bump;
2470    /// # let bump: Bump = Bump::try_new()?;
2471    /// let mut uninit = bump.try_alloc_uninit()?;
2472    ///
2473    /// let five = unsafe {
2474    ///     uninit.write(5);
2475    ///     uninit.assume_init()
2476    /// };
2477    ///
2478    /// assert_eq!(*five, 5);
2479    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2480    /// ```
2481    #[inline(always)]
2482    pub fn try_alloc_uninit<T>(&self) -> Result<BumpBox<'a, MaybeUninit<T>>, AllocError> {
2483        self.generic_alloc_uninit()
2484    }
2485
2486    #[inline(always)]
2487    pub(crate) fn generic_alloc_uninit<B: ErrorBehavior, T>(&self) -> Result<BumpBox<'a, MaybeUninit<T>>, B> {
2488        if T::IS_ZST {
2489            return Ok(BumpBox::zst(MaybeUninit::uninit()));
2490        }
2491
2492        let ptr = self.do_alloc_sized::<B, T>()?.cast::<MaybeUninit<T>>();
2493        unsafe { Ok(BumpBox::from_raw(ptr)) }
2494    }
2495
2496    /// Allocate an unitialized object slice.
2497    ///
2498    /// You can safely initialize the object with
2499    /// [`init_fill`](BumpBox::init_fill),
2500    /// [`init_fill_with`](BumpBox::init_fill_with),
2501    /// [`init_copy`](BumpBox::init_copy),
2502    /// [`init_clone`](BumpBox::init_clone),
2503    /// [`init_zeroed`](crate::zerocopy_08::InitZeroed::init_zeroed) or unsafely with
2504    /// [`assume_init`](BumpBox::assume_init).
2505    ///
2506    /// # Panics
2507    /// Panics if the allocation fails.
2508    ///
2509    /// # Examples
2510    /// Safely:
2511    /// ```
2512    /// # use bump_scope::Bump;
2513    /// # let bump: Bump = Bump::new();
2514    /// let uninit = bump.alloc_uninit_slice(3);
2515    ///
2516    /// let values = uninit.init_copy(&[1, 2, 3]);
2517    ///
2518    /// assert_eq!(values, [1, 2, 3])
2519    /// ```
2520    ///
2521    /// Unsafely:
2522    /// ```
2523    /// # use bump_scope::Bump;
2524    /// # let bump: Bump = Bump::new();
2525    /// let mut uninit = bump.alloc_uninit_slice(3);
2526    ///
2527    /// let values = unsafe {
2528    ///     uninit[0].write(1);
2529    ///     uninit[1].write(2);
2530    ///     uninit[2].write(3);
2531    ///
2532    ///     uninit.assume_init()
2533    /// };
2534    ///
2535    /// assert_eq!(values, [1, 2, 3]);
2536    /// ```
2537    #[inline(always)]
2538    #[cfg(feature = "panic-on-alloc")]
2539    pub fn alloc_uninit_slice<T>(&self, len: usize) -> BumpBox<'a, [MaybeUninit<T>]> {
2540        panic_on_error(self.generic_alloc_uninit_slice(len))
2541    }
2542
2543    /// Allocate an unitialized object slice.
2544    ///
2545    /// You can safely initialize the object with
2546    /// [`init_fill`](BumpBox::init_fill),
2547    /// [`init_fill_with`](BumpBox::init_fill_with),
2548    /// [`init_copy`](BumpBox::init_copy),
2549    /// [`init_clone`](BumpBox::init_clone),
2550    /// [`init_zeroed`](crate::zerocopy_08::InitZeroed::init_zeroed) or unsafely with
2551    /// [`assume_init`](BumpBox::assume_init).
2552    ///
2553    /// # Errors
2554    /// Errors if the allocation fails.
2555    ///
2556    /// # Examples
2557    /// Safely:
2558    /// ```
2559    /// # use bump_scope::Bump;
2560    /// # let bump: Bump = Bump::new();
2561    /// let uninit = bump.try_alloc_uninit_slice(3)?;
2562    ///
2563    /// let values = uninit.init_copy(&[1, 2, 3]);
2564    ///
2565    /// assert_eq!(values, [1, 2, 3]);
2566    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2567    /// ```
2568    ///
2569    /// Unsafely:
2570    /// ```
2571    /// # use bump_scope::Bump;
2572    /// # let bump: Bump = Bump::try_new()?;
2573    /// let mut uninit = bump.try_alloc_uninit_slice(3)?;
2574    ///
2575    /// let values = unsafe {
2576    ///     uninit[0].write(1);
2577    ///     uninit[1].write(2);
2578    ///     uninit[2].write(3);
2579    ///
2580    ///     uninit.assume_init()
2581    /// };
2582    ///
2583    /// assert_eq!(values, [1, 2, 3]);
2584    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2585    /// ```
2586    #[inline(always)]
2587    pub fn try_alloc_uninit_slice<T>(&self, len: usize) -> Result<BumpBox<'a, [MaybeUninit<T>]>, AllocError> {
2588        self.generic_alloc_uninit_slice(len)
2589    }
2590
2591    #[inline(always)]
2592    pub(crate) fn generic_alloc_uninit_slice<B: ErrorBehavior, T>(
2593        &self,
2594        len: usize,
2595    ) -> Result<BumpBox<'a, [MaybeUninit<T>]>, B> {
2596        if T::IS_ZST {
2597            return Ok(BumpBox::uninit_zst_slice(len));
2598        }
2599
2600        let ptr = self.do_alloc_slice::<B, T>(len)?.cast::<MaybeUninit<T>>();
2601
2602        unsafe {
2603            let ptr = NonNull::slice_from_raw_parts(ptr, len);
2604            Ok(BumpBox::from_raw(ptr))
2605        }
2606    }
2607
2608    /// Allocate an unitialized object slice.
2609    ///
2610    /// You can safely initialize the object with
2611    /// [`init_fill`](BumpBox::init_fill),
2612    /// [`init_fill_with`](BumpBox::init_fill_with),
2613    /// [`init_copy`](BumpBox::init_copy),
2614    /// [`init_clone`](BumpBox::init_clone),
2615    /// [`init_zeroed`](crate::zerocopy_08::InitZeroed::init_zeroed) or unsafely with
2616    /// [`assume_init`](BumpBox::assume_init).
2617    ///
2618    /// This is just like [`alloc_uninit_slice`](Self::alloc_uninit_slice) but uses a `slice` to provide the `len`.
2619    /// This avoids a check for a valid layout. The elements of `slice` are irrelevant.
2620    ///
2621    /// # Panics
2622    /// Panics if the allocation fails.
2623    ///
2624    /// # Examples
2625    /// ```
2626    /// # use bump_scope::Bump;
2627    /// # let bump: Bump = Bump::new();
2628    /// let slice = &[1, 2, 3];
2629    /// let uninit_slice = bump.alloc_uninit_slice_for(slice);
2630    /// assert_eq!(uninit_slice.len(), 3);
2631    /// ```
2632    #[inline(always)]
2633    #[cfg(feature = "panic-on-alloc")]
2634    pub fn alloc_uninit_slice_for<T>(&self, slice: &[T]) -> BumpBox<'a, [MaybeUninit<T>]> {
2635        panic_on_error(self.generic_alloc_uninit_slice_for(slice))
2636    }
2637
2638    /// Allocate an unitialized object slice.
2639    ///
2640    /// You can safely initialize the object with
2641    /// [`init_fill`](BumpBox::init_fill),
2642    /// [`init_fill_with`](BumpBox::init_fill_with),
2643    /// [`init_copy`](BumpBox::init_copy),
2644    /// [`init_clone`](BumpBox::init_clone),
2645    /// [`init_zeroed`](crate::zerocopy_08::InitZeroed::init_zeroed) or unsafely with
2646    /// [`assume_init`](BumpBox::assume_init).
2647    ///
2648    /// This is just like [`try_alloc_uninit_slice`](Self::try_alloc_uninit_slice) but uses a `slice` to provide the `len`.
2649    /// This avoids a check for a valid layout. The elements of `slice` are irrelevant.
2650    ///
2651    /// # Errors
2652    /// Errors if the allocation fails.
2653    ///
2654    /// # Examples
2655    /// ```
2656    /// # use bump_scope::Bump;
2657    /// # let bump: Bump = Bump::try_new()?;
2658    /// let slice = &[1, 2, 3];
2659    /// let uninit_slice = bump.try_alloc_uninit_slice_for(slice)?;
2660    /// assert_eq!(uninit_slice.len(), 3);
2661    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2662    /// ```
2663    #[inline(always)]
2664    pub fn try_alloc_uninit_slice_for<T>(&self, slice: &[T]) -> Result<BumpBox<'a, [MaybeUninit<T>]>, AllocError> {
2665        self.generic_alloc_uninit_slice_for(slice)
2666    }
2667
2668    #[inline(always)]
2669    pub(crate) fn generic_alloc_uninit_slice_for<B: ErrorBehavior, T>(
2670        &self,
2671        slice: &[T],
2672    ) -> Result<BumpBox<'a, [MaybeUninit<T>]>, B> {
2673        if T::IS_ZST {
2674            return Ok(BumpBox::uninit_zst_slice(slice.len()));
2675        }
2676
2677        let ptr = self.do_alloc_slice_for::<B, T>(slice)?.cast::<MaybeUninit<T>>();
2678
2679        unsafe {
2680            let ptr = NonNull::slice_from_raw_parts(ptr, slice.len());
2681            Ok(BumpBox::from_raw(ptr))
2682        }
2683    }
2684
2685    /// Allocate a [`FixedBumpVec`] with the given `capacity`.
2686    ///
2687    /// # Panics
2688    /// Panics if the allocation fails.
2689    ///
2690    /// # Examples
2691    /// ```
2692    /// # use bump_scope::Bump;
2693    /// # let bump: Bump = Bump::new();
2694    /// # #[expect(deprecated)]
2695    /// let mut values = bump.alloc_fixed_vec(3);
2696    /// values.push(1);
2697    /// values.push(2);
2698    /// values.push(3);
2699    /// assert_eq!(values, [1, 2, 3])
2700    /// ```
2701    #[doc(hidden)]
2702    #[deprecated = "use `FixedBumpVec::with_capacity_in()` instead"]
2703    #[inline(always)]
2704    #[cfg(feature = "panic-on-alloc")]
2705    pub fn alloc_fixed_vec<T>(&self, capacity: usize) -> FixedBumpVec<'a, T> {
2706        panic_on_error(self.generic_alloc_fixed_vec(capacity))
2707    }
2708
2709    /// Allocate a [`FixedBumpVec`] with the given `capacity`.
2710    ///
2711    /// # Errors
2712    /// Errors if the allocation fails.
2713    ///
2714    /// # Examples
2715    /// ```
2716    /// # use bump_scope::Bump;
2717    /// # let bump: Bump = Bump::try_new()?;
2718    /// # #[expect(deprecated)]
2719    /// let mut values = bump.try_alloc_fixed_vec(3)?;
2720    /// values.push(1);
2721    /// values.push(2);
2722    /// values.push(3);
2723    /// assert_eq!(values, [1, 2, 3]);
2724    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2725    /// ```
2726    #[doc(hidden)]
2727    #[deprecated = "use `FixedBumpVec::try_with_capacity_in()` instead"]
2728    #[inline(always)]
2729    pub fn try_alloc_fixed_vec<T>(&self, capacity: usize) -> Result<FixedBumpVec<'a, T>, AllocError> {
2730        self.generic_alloc_fixed_vec(capacity)
2731    }
2732
2733    #[inline(always)]
2734    pub(crate) fn generic_alloc_fixed_vec<B: ErrorBehavior, T>(&self, capacity: usize) -> Result<FixedBumpVec<'a, T>, B> {
2735        Ok(FixedBumpVec::from_uninit(self.generic_alloc_uninit_slice(capacity)?))
2736    }
2737
2738    /// Allocate a [`FixedBumpString`] with the given `capacity` in bytes.
2739    ///
2740    /// # Panics
2741    /// Panics if the allocation fails.
2742    ///
2743    /// # Examples
2744    /// ```
2745    /// # use bump_scope::Bump;
2746    /// # let bump: Bump = Bump::new();
2747    /// # #[expect(deprecated)]
2748    /// let mut string = bump.alloc_fixed_string(13);
2749    /// string.push_str("Hello,");
2750    /// string.push_str(" world!");
2751    /// assert_eq!(string, "Hello, world!");
2752    /// ```
2753    #[doc(hidden)]
2754    #[deprecated = "use `FixedBumpString::with_capacity_in()` instead"]
2755    #[inline(always)]
2756    #[cfg(feature = "panic-on-alloc")]
2757    pub fn alloc_fixed_string(&self, capacity: usize) -> FixedBumpString<'a> {
2758        panic_on_error(self.generic_alloc_fixed_string(capacity))
2759    }
2760
2761    /// Allocate a [`FixedBumpString`] with the given `capacity` in bytes.
2762    ///
2763    /// # Errors
2764    /// Errors if the allocation fails.
2765    ///
2766    /// # Examples
2767    /// ```
2768    /// # use bump_scope::Bump;
2769    /// # let bump: Bump = Bump::try_new()?;
2770    /// # #[expect(deprecated)]
2771    /// let mut string = bump.try_alloc_fixed_string(13)?;
2772    /// string.push_str("Hello,");
2773    /// string.push_str(" world!");
2774    /// assert_eq!(string, "Hello, world!");
2775    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2776    /// ```
2777    #[doc(hidden)]
2778    #[deprecated = "use `FixedBumpString::try_with_capacity_in()` instead"]
2779    #[inline(always)]
2780    pub fn try_alloc_fixed_string(&self, capacity: usize) -> Result<FixedBumpString<'a>, AllocError> {
2781        self.generic_alloc_fixed_string(capacity)
2782    }
2783
2784    #[inline(always)]
2785    pub(crate) fn generic_alloc_fixed_string<B: ErrorBehavior>(&self, capacity: usize) -> Result<FixedBumpString<'a>, B> {
2786        Ok(FixedBumpString::from_uninit(self.generic_alloc_uninit_slice(capacity)?))
2787    }
2788
2789    /// Allocates memory as described by the given `Layout`.
2790    ///
2791    /// # Panics
2792    /// Panics if the allocation fails.
2793    #[inline(always)]
2794    #[cfg(feature = "panic-on-alloc")]
2795    pub fn alloc_layout(&self, layout: Layout) -> NonNull<u8> {
2796        panic_on_error(self.generic_alloc_layout(layout))
2797    }
2798
2799    /// Allocates memory as described by the given `Layout`.
2800    ///
2801    /// # Errors
2802    /// Errors if the allocation fails.
2803    #[inline(always)]
2804    pub fn try_alloc_layout(&self, layout: Layout) -> Result<NonNull<u8>, AllocError> {
2805        self.generic_alloc_layout(layout)
2806    }
2807
2808    #[inline(always)]
2809    pub(crate) fn generic_alloc_layout<B: ErrorBehavior>(&self, layout: Layout) -> Result<NonNull<u8>, B> {
2810        match self.chunk.get().alloc(MinimumAlignment::<MIN_ALIGN>, CustomLayout(layout)) {
2811            Some(ptr) => Ok(ptr),
2812            None => self.alloc_in_another_chunk(layout),
2813        }
2814    }
2815
2816    /// Drops an allocated value and attempts to free its memory.
2817    ///
2818    /// The memory can only be freed if this is the last allocation.
2819    ///
2820    /// # Examples
2821    /// ```
2822    /// # use bump_scope::Bump;
2823    /// # let bump: Bump = Bump::new();
2824    /// let boxed = bump.alloc(3i32);
2825    /// assert_eq!(bump.stats().allocated(), 4);
2826    /// bump.dealloc(boxed);
2827    /// assert_eq!(bump.stats().allocated(), 0);
2828    /// ```
2829    #[inline(always)]
2830    pub fn dealloc<T: ?Sized>(&self, boxed: BumpBox<T>) {
2831        let layout = Layout::for_value::<T>(&boxed);
2832        let ptr = boxed.into_raw();
2833
2834        unsafe {
2835            ptr.drop_in_place();
2836            self.deallocate(ptr.cast(), layout);
2837        }
2838    }
2839
2840    /// Reserves capacity for at least `additional` more bytes to be bump allocated.
2841    /// The bump allocator may reserve more space to avoid frequent reallocations.
2842    /// After calling `reserve_bytes`, <code>self.[stats](Self::stats)().[remaining](Stats::remaining)()</code> will be greater than or equal to
2843    /// `additional`. Does nothing if the capacity is already sufficient.
2844    ///
2845    /// Note that these additional bytes are not necessarily in one contiguous region but
2846    /// might be spread out among many chunks.
2847    ///
2848    /// # Panics
2849    /// Panics if the allocation fails.
2850    ///
2851    /// # Examples
2852    /// ```
2853    /// # use bump_scope::Bump;
2854    /// let bump: Bump = Bump::new();
2855    /// assert!(bump.stats().capacity() < 4096);
2856    ///
2857    /// bump.reserve_bytes(4096);
2858    /// assert!(bump.stats().capacity() >= 4096);
2859    /// ```
2860    #[inline(always)]
2861    #[cfg(feature = "panic-on-alloc")]
2862    pub fn reserve_bytes(&self, additional: usize) {
2863        panic_on_error(self.generic_reserve_bytes(additional));
2864    }
2865
2866    /// Reserves capacity for at least `additional` more bytes to be bump allocated.
2867    /// The bump allocator may reserve more space to avoid frequent reallocations.
2868    /// After calling `reserve_bytes`, <code>self.[stats](Self::stats)().[remaining](Stats::remaining)()</code> will be greater than or equal to
2869    /// `additional`. Does nothing if the capacity is already sufficient.
2870    ///
2871    /// # Errors
2872    /// Errors if the allocation fails.
2873    ///
2874    /// # Examples
2875    /// ```
2876    /// # use bump_scope::Bump;
2877    /// let bump: Bump = Bump::try_new()?;
2878    /// assert!(bump.stats().capacity() < 4096);
2879    ///
2880    /// bump.try_reserve_bytes(4096)?;
2881    /// assert!(bump.stats().capacity() >= 4096);
2882    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2883    /// ```
2884    #[inline(always)]
2885    pub fn try_reserve_bytes(&self, additional: usize) -> Result<(), AllocError> {
2886        self.generic_reserve_bytes(additional)
2887    }
2888
2889    #[inline(always)]
2890    pub(crate) fn generic_reserve_bytes<B: ErrorBehavior>(&self, additional: usize) -> Result<(), B> {
2891        let Ok(layout) = Layout::from_size_align(additional, 1) else {
2892            return Err(B::capacity_overflow());
2893        };
2894
2895        if let Some(mut chunk) = self.chunk.get().guaranteed_allocated() {
2896            let mut additional = additional;
2897
2898            loop {
2899                if let Some(rest) = additional.checked_sub(chunk.remaining()) {
2900                    additional = rest;
2901                } else {
2902                    return Ok(());
2903                }
2904
2905                if let Some(next) = chunk.next() {
2906                    chunk = next;
2907                } else {
2908                    break;
2909                }
2910            }
2911
2912            chunk.append_for(layout).map(drop)
2913        } else {
2914            let allocator = A::default_or_panic();
2915            let new_chunk = RawChunk::new_in(
2916                ChunkSize::from_capacity(layout).ok_or_else(B::capacity_overflow)?,
2917                None,
2918                allocator,
2919            )?;
2920            self.chunk.set(new_chunk.coerce_guaranteed_allocated());
2921            Ok(())
2922        }
2923    }
2924
2925    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
2926    ///
2927    /// 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.
2928    ///
2929    /// There is also [`alloc_try_with_mut`](Self::alloc_try_with_mut), optimized for a mutable reference.
2930    ///
2931    /// # Panics
2932    /// Panics if the allocation fails.
2933    ///
2934    /// # Examples
2935    #[cfg_attr(feature = "nightly-tests", doc = "```")]
2936    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
2937    /// # #![feature(offset_of_enum)]
2938    /// # use core::mem::offset_of;
2939    /// # use bump_scope::Bump;
2940    /// # let bump: Bump = Bump::new();
2941    /// let result = bump.alloc_try_with(|| -> Result<i32, i32> { Ok(123) });
2942    /// assert_eq!(result.unwrap(), 123);
2943    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
2944    /// ```
2945    #[cfg_attr(feature = "nightly-tests", doc = "```")]
2946    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
2947    /// # use bump_scope::Bump;
2948    /// # let bump: Bump = Bump::new();
2949    /// let result = bump.alloc_try_with(|| -> Result<i32, i32> { Err(123) });
2950    /// assert_eq!(result.unwrap_err(), 123);
2951    /// assert_eq!(bump.stats().allocated(), 0);
2952    /// ```
2953    #[inline(always)]
2954    #[cfg(feature = "panic-on-alloc")]
2955    #[expect(clippy::missing_errors_doc)]
2956    pub fn alloc_try_with<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<BumpBox<'a, T>, E> {
2957        panic_on_error(self.generic_alloc_try_with(f))
2958    }
2959
2960    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
2961    ///
2962    /// 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.
2963    ///
2964    /// There is also [`try_alloc_try_with_mut`](Self::try_alloc_try_with_mut), optimized for a mutable reference.
2965    ///
2966    /// # Errors
2967    /// Errors if the allocation fails.
2968    ///
2969    /// # Examples
2970    #[cfg_attr(feature = "nightly-tests", doc = "```")]
2971    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
2972    /// # #![feature(offset_of_enum)]
2973    /// # use core::mem::offset_of;
2974    /// # use bump_scope::Bump;
2975    /// # let bump: Bump = Bump::try_new()?;
2976    /// let result = bump.try_alloc_try_with(|| -> Result<i32, i32> { Ok(123) })?;
2977    /// assert_eq!(result.unwrap(), 123);
2978    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
2979    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2980    /// ```
2981    #[cfg_attr(feature = "nightly-tests", doc = "```")]
2982    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
2983    /// # use bump_scope::Bump;
2984    /// # let bump: Bump = Bump::try_new()?;
2985    /// let result = bump.try_alloc_try_with(|| -> Result<i32, i32> { Err(123) })?;
2986    /// assert_eq!(result.unwrap_err(), 123);
2987    /// assert_eq!(bump.stats().allocated(), 0);
2988    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2989    /// ```
2990    #[inline(always)]
2991    pub fn try_alloc_try_with<T, E>(
2992        &self,
2993        f: impl FnOnce() -> Result<T, E>,
2994    ) -> Result<Result<BumpBox<'a, T>, E>, AllocError> {
2995        self.generic_alloc_try_with(f)
2996    }
2997
2998    #[inline(always)]
2999    pub(crate) fn generic_alloc_try_with<B: ErrorBehavior, T, E>(
3000        &self,
3001        f: impl FnOnce() -> Result<T, E>,
3002    ) -> Result<Result<BumpBox<'a, T>, E>, B> {
3003        if T::IS_ZST {
3004            return match f() {
3005                Ok(value) => Ok(Ok(BumpBox::zst(value))),
3006                Err(error) => Ok(Err(error)),
3007            };
3008        }
3009
3010        let checkpoint_before_alloc = self.checkpoint();
3011        let uninit = self.generic_alloc_uninit::<B, Result<T, E>>()?;
3012        let ptr = BumpBox::into_raw(uninit).cast::<Result<T, E>>();
3013
3014        // When bumping downwards the chunk's position is the same as `ptr`.
3015        // Using `ptr` is faster so we use that.
3016        let pos = if UP { self.chunk.get().pos() } else { ptr.cast() };
3017
3018        Ok(unsafe {
3019            non_null::write_with(ptr, f);
3020
3021            // If `f` made allocations on this bump allocator we can't shrink the allocation.
3022            let can_shrink = pos == self.chunk.get().pos();
3023
3024            match non_null::result(ptr) {
3025                Ok(value) => Ok({
3026                    if can_shrink {
3027                        let new_pos = if UP {
3028                            let pos = value.add(1).addr().get();
3029                            up_align_usize_unchecked(pos, MIN_ALIGN)
3030                        } else {
3031                            let pos = value.addr().get();
3032                            down_align_usize(pos, MIN_ALIGN)
3033                        };
3034
3035                        // The allocation of a non-ZST was successful, so our chunk must be allocated.
3036                        let chunk = self.chunk.get().guaranteed_allocated_unchecked();
3037                        chunk.set_pos_addr(new_pos);
3038                    }
3039
3040                    BumpBox::from_raw(value)
3041                }),
3042                Err(error) => Err({
3043                    let error = error.read();
3044
3045                    if can_shrink {
3046                        self.reset_to(checkpoint_before_alloc);
3047                    }
3048
3049                    error
3050                }),
3051            }
3052        })
3053    }
3054
3055    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
3056    ///
3057    /// 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.
3058    ///
3059    /// This is just like [`alloc_try_with`](Self::alloc_try_with), but optimized for a mutable reference.
3060    ///
3061    /// # Panics
3062    /// Panics if the allocation fails.
3063    ///
3064    /// # Examples
3065    #[cfg_attr(feature = "nightly-tests", doc = "```")]
3066    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
3067    /// # #![feature(offset_of_enum)]
3068    /// # use core::mem::offset_of;
3069    /// # use bump_scope::Bump;
3070    /// # let mut bump: Bump = Bump::new();
3071    /// let result = bump.alloc_try_with_mut(|| -> Result<i32, i32> { Ok(123) });
3072    /// assert_eq!(result.unwrap(), 123);
3073    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
3074    /// ```
3075    #[cfg_attr(feature = "nightly-tests", doc = "```")]
3076    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
3077    /// # use bump_scope::Bump;
3078    /// # let mut bump: Bump = Bump::new();
3079    /// let result = bump.alloc_try_with_mut(|| -> Result<i32, i32> { Err(123) });
3080    /// assert_eq!(result.unwrap_err(), 123);
3081    /// assert_eq!(bump.stats().allocated(), 0);
3082    /// ```
3083    #[inline(always)]
3084    #[cfg(feature = "panic-on-alloc")]
3085    #[expect(clippy::missing_errors_doc)]
3086    pub fn alloc_try_with_mut<T, E>(&mut self, f: impl FnOnce() -> Result<T, E>) -> Result<BumpBox<'a, T>, E> {
3087        panic_on_error(self.generic_alloc_try_with_mut(f))
3088    }
3089
3090    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
3091    ///
3092    /// 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.
3093    ///
3094    /// This is just like [`try_alloc_try_with`](Self::try_alloc_try_with), but optimized for a mutable reference.
3095    ///
3096    /// # Errors
3097    /// Errors if the allocation fails.
3098    ///
3099    /// # Examples
3100    #[cfg_attr(feature = "nightly-tests", doc = "```")]
3101    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
3102    /// # #![feature(offset_of_enum)]
3103    /// # use core::mem::offset_of;
3104    /// # use bump_scope::Bump;
3105    /// # let mut bump: Bump = Bump::try_new()?;
3106    /// let result = bump.try_alloc_try_with_mut(|| -> Result<i32, i32> { Ok(123) })?;
3107    /// assert_eq!(result.unwrap(), 123);
3108    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
3109    /// # Ok::<(), bump_scope::alloc::AllocError>(())
3110    /// ```
3111    #[cfg_attr(feature = "nightly-tests", doc = "```")]
3112    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
3113    /// # use bump_scope::Bump;
3114    /// # let mut bump: Bump = Bump::try_new()?;
3115    /// let result = bump.try_alloc_try_with_mut(|| -> Result<i32, i32> { Err(123) })?;
3116    /// assert_eq!(result.unwrap_err(), 123);
3117    /// assert_eq!(bump.stats().allocated(), 0);
3118    /// # Ok::<(), bump_scope::alloc::AllocError>(())
3119    /// ```
3120    #[inline(always)]
3121    pub fn try_alloc_try_with_mut<T, E>(
3122        &mut self,
3123        f: impl FnOnce() -> Result<T, E>,
3124    ) -> Result<Result<BumpBox<'a, T>, E>, AllocError> {
3125        self.generic_alloc_try_with_mut(f)
3126    }
3127
3128    #[inline(always)]
3129    pub(crate) fn generic_alloc_try_with_mut<B: ErrorBehavior, T, E>(
3130        &mut self,
3131        f: impl FnOnce() -> Result<T, E>,
3132    ) -> Result<Result<BumpBox<'a, T>, E>, B> {
3133        if T::IS_ZST {
3134            return match f() {
3135                Ok(value) => Ok(Ok(BumpBox::zst(value))),
3136                Err(error) => Ok(Err(error)),
3137            };
3138        }
3139
3140        let checkpoint = self.checkpoint();
3141        let ptr = self.generic_prepare_allocation::<B, Result<T, E>>()?;
3142
3143        Ok(unsafe {
3144            non_null::write_with(ptr, f);
3145
3146            // There is no need for `can_shrink` checks, because we have a mutable reference
3147            // so there's no way anyone else has allocated in `f`.
3148            match non_null::result(ptr) {
3149                Ok(value) => Ok({
3150                    let new_pos = if UP {
3151                        let pos = value.add(1).addr().get();
3152                        up_align_usize_unchecked(pos, MIN_ALIGN)
3153                    } else {
3154                        let pos = value.addr().get();
3155                        down_align_usize(pos, MIN_ALIGN)
3156                    };
3157
3158                    // The allocation of a non-ZST was successful, so our chunk must be allocated.
3159                    let chunk = self.chunk.get().guaranteed_allocated_unchecked();
3160                    chunk.set_pos_addr(new_pos);
3161
3162                    BumpBox::from_raw(value)
3163                }),
3164                Err(error) => Err({
3165                    let error = error.read();
3166                    self.reset_to(checkpoint);
3167                    error
3168                }),
3169            }
3170        })
3171    }
3172}