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(chunk) = self.chunk.get().guaranteed_allocated() {
1085                while let Some(chunk) = chunk.next() {
1086                    // We don't reset the chunk position when we leave a scope, so we need to do it here.
1087                    chunk.reset();
1088
1089                    self.chunk.set(chunk.coerce_guaranteed_allocated());
1090
1091                    if let Some(ptr) = f(chunk, layout) {
1092                        return Ok(ptr);
1093                    }
1094                }
1095
1096                // there is no chunk that fits, we need a new chunk
1097                chunk.append_for(*layout)
1098            } else {
1099                // When this bump allocator is unallocated, `A` is guaranteed to implement `Default`,
1100                // `default_or_panic` will not panic.
1101                let allocator = A::default_or_panic();
1102
1103                RawChunk::new_in(
1104                    ChunkSize::from_capacity(*layout).ok_or_else(B::capacity_overflow)?,
1105                    None,
1106                    allocator,
1107                )
1108            }?;
1109
1110            self.chunk.set(new_chunk.coerce_guaranteed_allocated());
1111
1112            match f(new_chunk, layout) {
1113                Some(ptr) => Ok(ptr),
1114                _ => {
1115                    // SAFETY: We just appended a chunk for that specific layout, it must have enough space.
1116                    // We don't panic here so we don't produce any panic code when using `try_` apis.
1117                    // We check for that in `test-fallibility`.
1118                    core::hint::unreachable_unchecked()
1119                }
1120            }
1121        }
1122    }
1123}
1124
1125impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> NoDrop
1126    for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
1127{
1128}
1129
1130/// Methods to allocate. Available as fallible or infallible.
1131impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool>
1132    BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
1133where
1134    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
1135    A: BaseAllocator<GUARANTEED_ALLOCATED>,
1136{
1137    /// Allocate an object.
1138    ///
1139    /// # Panics
1140    /// Panics if the allocation fails.
1141    ///
1142    /// # Examples
1143    /// ```
1144    /// # use bump_scope::Bump;
1145    /// # let bump: Bump = Bump::new();
1146    /// let allocated = bump.alloc(123);
1147    /// assert_eq!(allocated, 123);
1148    /// ```
1149    #[inline(always)]
1150    #[cfg(feature = "panic-on-alloc")]
1151    pub fn alloc<T>(&self, value: T) -> BumpBox<'a, T> {
1152        panic_on_error(self.generic_alloc(value))
1153    }
1154
1155    /// Allocate an object.
1156    ///
1157    /// # Errors
1158    /// Errors if the allocation fails.
1159    ///
1160    /// # Examples
1161    /// ```
1162    /// # use bump_scope::Bump;
1163    /// # let bump: Bump = Bump::try_new()?;
1164    /// let allocated = bump.try_alloc(123)?;
1165    /// assert_eq!(allocated, 123);
1166    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1167    /// ```
1168    #[inline(always)]
1169    pub fn try_alloc<T>(&self, value: T) -> Result<BumpBox<'a, T>, AllocError> {
1170        self.generic_alloc(value)
1171    }
1172
1173    #[inline(always)]
1174    pub(crate) fn generic_alloc<B: ErrorBehavior, T>(&self, value: T) -> Result<BumpBox<'a, T>, B> {
1175        self.generic_alloc_with(|| value)
1176    }
1177
1178    /// Allocates space for an object, then calls `f` to produce the
1179    /// value to be put in that place.
1180    ///
1181    /// In some cases this could be more performant than `alloc(f())` because it
1182    /// permits the compiler to directly place `T` in the allocated memory instead of
1183    /// constructing it on the stack and copying it over.
1184    ///
1185    /// # Panics
1186    /// Panics if the allocation fails.
1187    ///
1188    /// # Examples
1189    /// ```
1190    /// # use bump_scope::Bump;
1191    /// # let bump: Bump = Bump::new();
1192    /// let allocated = bump.alloc_with(|| 123);
1193    /// assert_eq!(allocated, 123);
1194    /// ```
1195    #[inline(always)]
1196    #[cfg(feature = "panic-on-alloc")]
1197    pub fn alloc_with<T>(&self, f: impl FnOnce() -> T) -> BumpBox<'a, T> {
1198        panic_on_error(self.generic_alloc_with(f))
1199    }
1200
1201    /// Allocates space for an object, then calls `f` to produce the
1202    /// value to be put in that place.
1203    ///
1204    /// In some cases this could be more performant than `try_alloc(f())` because it
1205    /// permits the compiler to directly place `T` in the allocated memory instead of
1206    /// constructing it on the stack and copying it over.
1207    ///
1208    /// # Errors
1209    /// Errors if the allocation fails.
1210    ///
1211    /// # Examples
1212    /// ```
1213    /// # use bump_scope::Bump;
1214    /// # let bump: Bump = Bump::try_new()?;
1215    /// let allocated = bump.try_alloc_with(|| 123)?;
1216    /// assert_eq!(allocated, 123);
1217    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1218    /// ```
1219    #[inline(always)]
1220    pub fn try_alloc_with<T>(&self, f: impl FnOnce() -> T) -> Result<BumpBox<'a, T>, AllocError> {
1221        self.generic_alloc_with(f)
1222    }
1223
1224    #[inline(always)]
1225    pub(crate) fn generic_alloc_with<B: ErrorBehavior, T>(&self, f: impl FnOnce() -> T) -> Result<BumpBox<'a, T>, B> {
1226        Ok(self.generic_alloc_uninit()?.init(f()))
1227    }
1228
1229    /// Allocate an object with its default value.
1230    ///
1231    /// This is equivalent to <code>[alloc_with](Self::alloc_with)(T::default)</code>.
1232    ///
1233    /// # Panics
1234    /// Panics if the allocation fails.
1235    ///
1236    /// # Examples
1237    /// ```
1238    /// # use bump_scope::Bump;
1239    /// # let bump: Bump = Bump::new();
1240    /// let allocated = bump.alloc_default::<i32>();
1241    /// assert_eq!(allocated, 0);
1242    /// ```
1243    #[inline(always)]
1244    #[cfg(feature = "panic-on-alloc")]
1245    pub fn alloc_default<T: Default>(&self) -> BumpBox<'a, T> {
1246        panic_on_error(self.generic_alloc_default())
1247    }
1248
1249    /// Allocate an object with its default value.
1250    ///
1251    /// This is equivalent to <code>[try_alloc_with](Self::try_alloc_with)(T::default)</code>.
1252    ///
1253    /// # Errors
1254    /// Errors if the allocation fails.
1255    ///
1256    /// # Examples
1257    /// ```
1258    /// # use bump_scope::Bump;
1259    /// # let bump: Bump = Bump::try_new()?;
1260    /// let allocated = bump.try_alloc_default()?;
1261    /// assert_eq!(allocated, 0);
1262    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1263    /// ```
1264    #[inline(always)]
1265    pub fn try_alloc_default<T: Default>(&self) -> Result<BumpBox<'a, T>, AllocError> {
1266        self.generic_alloc_default()
1267    }
1268
1269    #[inline(always)]
1270    pub(crate) fn generic_alloc_default<B: ErrorBehavior, T: Default>(&self) -> Result<BumpBox<'a, T>, B> {
1271        self.generic_alloc_with(Default::default)
1272    }
1273
1274    /// Allocate an object by cloning it.
1275    ///
1276    /// Unlike `alloc(value.clone())` this method also works for dynamically-sized types.
1277    ///
1278    /// # Panics
1279    /// Panics if the allocation fails.
1280    ///
1281    /// # Examples
1282    ///
1283    /// Allocate a `slice`, `str`, `CStr`, `Path`:
1284    #[cfg_attr(feature = "nightly-clone-to-uninit", doc = "```")]
1285    #[cfg_attr(not(feature = "nightly-clone-to-uninit"), doc = "```ignore")]
1286    /// #![feature(clone_to_uninit)]
1287    ///
1288    /// use std::path::Path;
1289    /// # use bump_scope::Bump;
1290    /// # let bump: Bump = Bump::new();
1291    ///
1292    /// let cloned = bump.alloc_clone(&[1, 2, 3]);
1293    /// assert_eq!(cloned, &[1, 2, 3]);
1294    ///
1295    /// let cloned = bump.alloc_clone("foo");
1296    /// assert_eq!(cloned, "foo");
1297    ///
1298    /// let cloned = bump.alloc_clone(c"foo");
1299    /// assert_eq!(cloned, c"foo");
1300    ///
1301    /// let cloned = bump.alloc_clone(Path::new("foo"));
1302    /// assert_eq!(cloned, Path::new("foo"));
1303    /// ```
1304    ///
1305    /// Allocate a trait object:
1306    #[cfg_attr(feature = "nightly-clone-to-uninit", doc = "```")]
1307    #[cfg_attr(not(feature = "nightly-clone-to-uninit"), doc = "```ignore")]
1308    /// #![feature(clone_to_uninit)]
1309    ///
1310    /// use core::clone::CloneToUninit;
1311    /// # use bump_scope::Bump;
1312    ///
1313    /// trait FnClone: Fn() -> String + CloneToUninit {}
1314    /// impl<T: ?Sized + Fn() -> String + CloneToUninit> FnClone for T {}
1315    ///
1316    /// // the closure references a local variable
1317    /// let reference = &String::from("Hello,");
1318    ///
1319    /// // and owns a string that it will have to clone
1320    /// let value = String::from("world!");
1321    ///
1322    /// let closure = move || format!("{reference} {value}");
1323    /// let object: &dyn FnClone = &closure;
1324    ///
1325    /// assert_eq!(object(), "Hello, world!");
1326    ///
1327    /// let bump: Bump = Bump::new();
1328    /// let object_clone = bump.alloc_clone(object);
1329    ///
1330    /// assert_eq!(object_clone(), "Hello, world!");
1331    /// ```
1332    #[cfg(feature = "nightly-clone-to-uninit")]
1333    pub fn alloc_clone<T: CloneToUninit + ?Sized>(&self, value: &T) -> BumpBox<'a, T> {
1334        panic_on_error(self.generic_alloc_clone(value))
1335    }
1336
1337    /// Allocate an object by cloning it.
1338    ///
1339    /// Unlike `alloc(value.clone())` this method also works for dynamically-sized types.
1340    ///
1341    /// # Errors
1342    /// Errors if the allocation fails.
1343    ///
1344    /// # Examples
1345    ///
1346    /// Allocate a `slice`, `str`, `CStr`, `Path`:
1347    #[cfg_attr(feature = "nightly-clone-to-uninit", doc = "```")]
1348    #[cfg_attr(not(feature = "nightly-clone-to-uninit"), doc = "```ignore")]
1349    /// #![feature(clone_to_uninit)]
1350    ///
1351    /// use std::path::Path;
1352    /// # use bump_scope::Bump;
1353    /// # let bump: Bump = Bump::try_new()?;
1354    ///
1355    /// let cloned = bump.try_alloc_clone(&[1, 2, 3])?;
1356    /// assert_eq!(cloned, &[1, 2, 3]);
1357    ///
1358    /// let cloned = bump.try_alloc_clone("foo")?;
1359    /// assert_eq!(cloned, "foo");
1360    ///
1361    /// let cloned = bump.try_alloc_clone(c"foo")?;
1362    /// assert_eq!(cloned, c"foo");
1363    ///
1364    /// let cloned = bump.try_alloc_clone(Path::new("foo"))?;
1365    /// assert_eq!(cloned, Path::new("foo"));
1366    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1367    /// ```
1368    ///
1369    /// Allocate a trait object:
1370    #[cfg_attr(feature = "nightly-clone-to-uninit", doc = "```")]
1371    #[cfg_attr(not(feature = "nightly-clone-to-uninit"), doc = "```ignore")]
1372    /// #![feature(clone_to_uninit)]
1373    ///
1374    /// use core::clone::CloneToUninit;
1375    /// # use bump_scope::Bump;
1376    ///
1377    /// trait FnClone: Fn() -> String + CloneToUninit {}
1378    /// impl<T: ?Sized + Fn() -> String + CloneToUninit> FnClone for T {}
1379    ///
1380    /// // the closure references a local variable
1381    /// let reference = &String::from("Hello,");
1382    ///
1383    /// // and owns a string that it will have to clone
1384    /// let value = String::from("world!");
1385    ///
1386    /// let closure = move || format!("{reference} {value}");
1387    /// let object: &dyn FnClone = &closure;
1388    ///
1389    /// assert_eq!(object(), "Hello, world!");
1390    ///
1391    /// let bump: Bump = Bump::try_new()?;
1392    /// let object_clone = bump.try_alloc_clone(object)?;
1393    ///
1394    /// assert_eq!(object_clone(), "Hello, world!");
1395    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1396    /// ```
1397    #[cfg(feature = "nightly-clone-to-uninit")]
1398    pub fn try_alloc_clone<T: CloneToUninit + ?Sized>(&self, value: &T) -> Result<BumpBox<'a, T>, AllocError> {
1399        self.generic_alloc_clone(value)
1400    }
1401
1402    #[cfg(feature = "nightly-clone-to-uninit")]
1403    pub(crate) fn generic_alloc_clone<B: ErrorBehavior, T: CloneToUninit + ?Sized>(
1404        &self,
1405        value: &T,
1406    ) -> Result<BumpBox<'a, T>, B> {
1407        let data = self.generic_alloc_layout(Layout::for_value(value))?;
1408        let metadata = ptr::metadata(value);
1409
1410        unsafe {
1411            value.clone_to_uninit(data.as_ptr());
1412            let ptr = ptr::from_raw_parts_mut(data.as_ptr(), metadata);
1413            let ptr = NonNull::new_unchecked(ptr);
1414            Ok(BumpBox::from_raw(ptr))
1415        }
1416    }
1417
1418    /// Allocate a slice and fill it by moving elements from an existing slice.
1419    ///
1420    /// # Panics
1421    /// Panics if the allocation fails.
1422    ///
1423    /// # Examples
1424    /// ```
1425    /// # use bump_scope::Bump;
1426    /// # let bump: Bump = Bump::new();
1427    /// // by value
1428    /// let a = bump.alloc_slice_move([1, 2]);
1429    /// let b = bump.alloc_slice_move(vec![3, 4]);
1430    /// let c = bump.alloc_slice_move(bump.alloc_iter(5..=6));
1431    ///
1432    /// // by mutable reference
1433    /// let mut other = vec![7, 8];
1434    /// let d = bump.alloc_slice_move(&mut other);
1435    /// assert!(other.is_empty());
1436    ///
1437    /// assert_eq!(a, [1, 2]);
1438    /// assert_eq!(b, [3, 4]);
1439    /// assert_eq!(c, [5, 6]);
1440    /// assert_eq!(d, [7, 8]);
1441    /// ```
1442    #[inline(always)]
1443    #[cfg(feature = "panic-on-alloc")]
1444    pub fn alloc_slice_move<T>(&self, slice: impl OwnedSlice<Item = T>) -> BumpBox<'a, [T]> {
1445        panic_on_error(self.generic_alloc_slice_move(slice))
1446    }
1447
1448    /// Allocate a slice and fill it by moving elements from an existing slice.
1449    ///
1450    /// # Errors
1451    /// Errors if the allocation fails.
1452    ///
1453    /// # Examples
1454    /// ```
1455    /// # use bump_scope::Bump;
1456    /// # let bump: Bump = Bump::try_new()?;
1457    /// // by value
1458    /// let a = bump.try_alloc_slice_move([1, 2])?;
1459    /// let b = bump.try_alloc_slice_move(vec![3, 4])?;
1460    /// let c = bump.try_alloc_slice_move(bump.alloc_iter(5..=6))?;
1461    ///
1462    /// // by mutable reference
1463    /// let mut other = vec![7, 8];
1464    /// let d = bump.try_alloc_slice_move(&mut other)?;
1465    /// assert!(other.is_empty());
1466    ///
1467    /// assert_eq!(a, [1, 2]);
1468    /// assert_eq!(b, [3, 4]);
1469    /// assert_eq!(c, [5, 6]);
1470    /// assert_eq!(d, [7, 8]);
1471    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1472    /// ```
1473    #[inline(always)]
1474    pub fn try_alloc_slice_move<T>(&self, slice: impl OwnedSlice<Item = T>) -> Result<BumpBox<'a, [T]>, AllocError> {
1475        self.generic_alloc_slice_move(slice)
1476    }
1477
1478    #[inline(always)]
1479    pub(crate) fn generic_alloc_slice_move<B: ErrorBehavior, T>(
1480        &self,
1481        slice: impl OwnedSlice<Item = T>,
1482    ) -> Result<BumpBox<'a, [T]>, B> {
1483        Ok(BumpVec::generic_from_owned_slice_in(slice, self)?.into_boxed_slice())
1484    }
1485
1486    /// Allocate a slice and fill it by `Copy`ing elements from an existing slice.
1487    ///
1488    /// # Panics
1489    /// Panics if the allocation fails.
1490    ///
1491    /// # Examples
1492    /// ```
1493    /// # use bump_scope::Bump;
1494    /// # let bump: Bump = Bump::new();
1495    /// let allocated = bump.alloc_slice_copy(&[1, 2, 3]);
1496    /// assert_eq!(allocated, [1, 2, 3]);
1497    /// ```
1498    #[inline(always)]
1499    #[cfg(feature = "panic-on-alloc")]
1500    pub fn alloc_slice_copy<T: Copy>(&self, slice: &[T]) -> BumpBox<'a, [T]> {
1501        panic_on_error(self.generic_alloc_slice_copy(slice))
1502    }
1503
1504    /// Allocate a slice and fill it by `Copy`ing elements from an existing slice.
1505    ///
1506    /// # Errors
1507    /// Errors if the allocation fails.
1508    ///
1509    /// # Examples
1510    /// ```
1511    /// # use bump_scope::Bump;
1512    /// # let bump: Bump = Bump::try_new()?;
1513    /// let allocated = bump.try_alloc_slice_copy(&[1, 2, 3])?;
1514    /// assert_eq!(allocated, [1, 2, 3]);
1515    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1516    /// ```
1517    #[inline(always)]
1518    pub fn try_alloc_slice_copy<T: Copy>(&self, slice: &[T]) -> Result<BumpBox<'a, [T]>, AllocError> {
1519        self.generic_alloc_slice_copy(slice)
1520    }
1521
1522    #[inline(always)]
1523    pub(crate) fn generic_alloc_slice_copy<B: ErrorBehavior, T: Copy>(&self, slice: &[T]) -> Result<BumpBox<'a, [T]>, B> {
1524        if T::IS_ZST {
1525            return Ok(BumpBox::zst_slice_clone(slice));
1526        }
1527
1528        let len = slice.len();
1529        let src = slice.as_ptr();
1530        let dst = self.do_alloc_slice_for(slice)?;
1531
1532        unsafe {
1533            core::ptr::copy_nonoverlapping(src, dst.as_ptr(), len);
1534            Ok(BumpBox::from_raw(NonNull::slice_from_raw_parts(dst, len)))
1535        }
1536    }
1537
1538    /// Allocate a slice and fill it by `Clone`ing elements from an existing slice.
1539    ///
1540    /// # Panics
1541    /// Panics if the allocation fails.
1542    ///
1543    /// # Examples
1544    /// ```
1545    /// # use bump_scope::Bump;
1546    /// # let bump: Bump = Bump::new();
1547    /// let allocated = bump.alloc_slice_clone(&[String::from("a"), String::from("b")]);
1548    /// assert_eq!(allocated, [String::from("a"), String::from("b")]);
1549    /// ```
1550    #[inline(always)]
1551    #[cfg(feature = "panic-on-alloc")]
1552    pub fn alloc_slice_clone<T: Clone>(&self, slice: &[T]) -> BumpBox<'a, [T]> {
1553        panic_on_error(self.generic_alloc_slice_clone(slice))
1554    }
1555
1556    /// Allocate a slice and fill it by `Clone`ing elements from an existing slice.
1557    ///
1558    /// # Errors
1559    /// Errors if the allocation fails.
1560    ///
1561    /// # Examples
1562    /// ```
1563    /// # use bump_scope::Bump;
1564    /// # let bump: Bump = Bump::try_new()?;
1565    /// let allocated = bump.try_alloc_slice_clone(&[String::from("a"), String::from("b")])?;
1566    /// assert_eq!(allocated, [String::from("a"), String::from("b")]);
1567    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1568    /// ```
1569    #[inline(always)]
1570    pub fn try_alloc_slice_clone<T: Clone>(&self, slice: &[T]) -> Result<BumpBox<'a, [T]>, AllocError> {
1571        self.generic_alloc_slice_clone(slice)
1572    }
1573
1574    #[inline(always)]
1575    pub(crate) fn generic_alloc_slice_clone<B: ErrorBehavior, T: Clone>(&self, slice: &[T]) -> Result<BumpBox<'a, [T]>, B> {
1576        if T::IS_ZST {
1577            return Ok(BumpBox::zst_slice_clone(slice));
1578        }
1579
1580        Ok(self.generic_alloc_uninit_slice_for(slice)?.init_clone(slice))
1581    }
1582
1583    /// Allocate a slice and fill it with elements by cloning `value`.
1584    ///
1585    /// # Panics
1586    /// Panics if the allocation fails.
1587    ///
1588    /// # Examples
1589    /// ```
1590    /// # use bump_scope::Bump;
1591    /// # let bump: Bump = Bump::new();
1592    /// let allocated = bump.alloc_slice_fill(3, "ho");
1593    /// assert_eq!(allocated, ["ho", "ho", "ho"]);
1594    /// ```
1595    #[inline(always)]
1596    #[cfg(feature = "panic-on-alloc")]
1597    pub fn alloc_slice_fill<T: Clone>(&self, len: usize, value: T) -> BumpBox<'a, [T]> {
1598        panic_on_error(self.generic_alloc_slice_fill(len, value))
1599    }
1600
1601    /// Allocate a slice and fill it with elements by cloning `value`.
1602    ///
1603    /// # Errors
1604    /// Errors if the allocation fails.
1605    ///
1606    /// # Examples
1607    /// ```
1608    /// # use bump_scope::Bump;
1609    /// # let bump: Bump = Bump::try_new()?;
1610    /// let allocated = bump.try_alloc_slice_fill(3, "ho")?;
1611    /// assert_eq!(allocated, ["ho", "ho", "ho"]);
1612    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1613    /// ```
1614    #[inline(always)]
1615    pub fn try_alloc_slice_fill<T: Clone>(&self, len: usize, value: T) -> Result<BumpBox<'a, [T]>, AllocError> {
1616        self.generic_alloc_slice_fill(len, value)
1617    }
1618
1619    #[inline(always)]
1620    pub(crate) fn generic_alloc_slice_fill<B: ErrorBehavior, T: Clone>(
1621        &self,
1622        len: usize,
1623        value: T,
1624    ) -> Result<BumpBox<'a, [T]>, B> {
1625        if T::IS_ZST {
1626            return Ok(BumpBox::zst_slice_fill(len, value));
1627        }
1628
1629        Ok(self.generic_alloc_uninit_slice(len)?.init_fill(value))
1630    }
1631
1632    /// Allocates a slice by fill it with elements returned by calling a closure repeatedly.
1633    ///
1634    /// This method uses a closure to create new values. If you'd rather
1635    /// [`Clone`] a given value, use [`alloc_slice_fill`](Self::alloc_slice_fill). If you want to use the [`Default`]
1636    /// trait to generate values, you can pass [`Default::default`] as the
1637    /// argument.
1638    ///
1639    /// # Panics
1640    /// Panics if the allocation fails.
1641    ///
1642    /// # Examples
1643    /// ```
1644    /// # use bump_scope::Bump;
1645    /// # let bump: Bump = Bump::new();
1646    /// let allocated = bump.alloc_slice_fill_with::<i32>(3, Default::default);
1647    /// assert_eq!(allocated, [0, 0, 0]);
1648    /// ```
1649    #[inline(always)]
1650    #[cfg(feature = "panic-on-alloc")]
1651    pub fn alloc_slice_fill_with<T>(&self, len: usize, f: impl FnMut() -> T) -> BumpBox<'a, [T]> {
1652        panic_on_error(self.generic_alloc_slice_fill_with(len, f))
1653    }
1654
1655    /// Allocates a slice by fill it with elements returned by calling a closure repeatedly.
1656    ///
1657    /// This method uses a closure to create new values. If you'd rather
1658    /// [`Clone`] a given value, use [`try_alloc_slice_fill`](Self::try_alloc_slice_fill). If you want to use the [`Default`]
1659    /// trait to generate values, you can pass [`Default::default`] as the
1660    /// argument.
1661    ///
1662    /// # Errors
1663    /// Errors if the allocation fails.
1664    ///
1665    /// # Examples
1666    /// ```
1667    /// # use bump_scope::Bump;
1668    /// # let bump: Bump = Bump::try_new()?;
1669    /// let allocated = bump.try_alloc_slice_fill_with::<i32>(3, Default::default)?;
1670    /// assert_eq!(allocated, [0, 0, 0]);
1671    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1672    /// ```
1673    #[inline(always)]
1674    pub fn try_alloc_slice_fill_with<T>(&self, len: usize, f: impl FnMut() -> T) -> Result<BumpBox<'a, [T]>, AllocError> {
1675        self.generic_alloc_slice_fill_with(len, f)
1676    }
1677
1678    #[inline(always)]
1679    pub(crate) fn generic_alloc_slice_fill_with<B: ErrorBehavior, T>(
1680        &self,
1681        len: usize,
1682        f: impl FnMut() -> T,
1683    ) -> Result<BumpBox<'a, [T]>, B> {
1684        if T::IS_ZST {
1685            return Ok(BumpBox::zst_slice_fill_with(len, f));
1686        }
1687
1688        Ok(self.generic_alloc_uninit_slice(len)?.init_fill_with(f))
1689    }
1690
1691    /// Allocate a `str`.
1692    ///
1693    /// # Panics
1694    /// Panics if the allocation fails.
1695    ///
1696    /// # Examples
1697    /// ```
1698    /// # use bump_scope::Bump;
1699    /// # let bump: Bump = Bump::new();
1700    /// let allocated = bump.alloc_str("Hello, world!");
1701    /// assert_eq!(allocated, "Hello, world!");
1702    /// ```
1703    #[inline(always)]
1704    #[cfg(feature = "panic-on-alloc")]
1705    pub fn alloc_str(&self, src: &str) -> BumpBox<'a, str> {
1706        panic_on_error(self.generic_alloc_str(src))
1707    }
1708
1709    /// Allocate a `str`.
1710    ///
1711    /// # Errors
1712    /// Errors if the allocation fails.
1713    ///
1714    /// # Examples
1715    /// ```
1716    /// # use bump_scope::Bump;
1717    /// # let bump: Bump = Bump::try_new()?;
1718    /// let allocated = bump.try_alloc_str("Hello, world!")?;
1719    /// assert_eq!(allocated, "Hello, world!");
1720    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1721    /// ```
1722    #[inline(always)]
1723    pub fn try_alloc_str(&self, src: &str) -> Result<BumpBox<'a, str>, AllocError> {
1724        self.generic_alloc_str(src)
1725    }
1726
1727    #[inline(always)]
1728    pub(crate) fn generic_alloc_str<B: ErrorBehavior>(&self, src: &str) -> Result<BumpBox<'a, str>, B> {
1729        let slice = self.generic_alloc_slice_copy(src.as_bytes())?;
1730
1731        // SAFETY: input is `str` so this is too
1732        Ok(unsafe { BumpBox::from_utf8_unchecked(slice) })
1733    }
1734
1735    /// Allocate a `str` from format arguments.
1736    ///
1737    /// If you have a `&mut self` you can use [`alloc_fmt_mut`](Self::alloc_fmt_mut)
1738    /// instead for better performance.
1739    ///
1740    /// # Panics
1741    /// Panics if the allocation fails.
1742    ///
1743    /// This technically also panics if the `fmt()` implementation returned an Error,
1744    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1745    /// that should be equivalent to an allocation failure.
1746    ///
1747    /// # Examples
1748    /// ```
1749    /// # use bump_scope::Bump;
1750    /// # let bump: Bump = Bump::new();
1751    /// let one = 1;
1752    /// let two = 2;
1753    /// let string = bump.alloc_fmt(format_args!("{one} + {two} = {}", one + two));
1754    ///
1755    /// assert_eq!(string, "1 + 2 = 3");
1756    /// ```
1757    #[inline(always)]
1758    #[cfg(feature = "panic-on-alloc")]
1759    pub fn alloc_fmt(&self, args: fmt::Arguments) -> BumpBox<'a, str> {
1760        panic_on_error(self.generic_alloc_fmt(args))
1761    }
1762
1763    /// Allocate a `str` from format arguments.
1764    ///
1765    /// If you have a `&mut self` you can use [`try_alloc_fmt_mut`](Self::try_alloc_fmt_mut)
1766    /// instead for better performance.
1767    ///
1768    /// # Errors
1769    /// Errors if the allocation fails.
1770    ///
1771    /// This technically also errors if the `fmt()` implementation returned an Error,
1772    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1773    /// that should be equivalent to an allocation failure.
1774    ///
1775    /// # Examples
1776    /// ```
1777    /// # use bump_scope::Bump;
1778    /// # let bump: Bump = Bump::try_new()?;
1779    /// let one = 1;
1780    /// let two = 2;
1781    /// let string = bump.try_alloc_fmt(format_args!("{one} + {two} = {}", one + two))?;
1782    ///
1783    /// assert_eq!(string, "1 + 2 = 3");
1784    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1785    /// ```
1786    #[inline(always)]
1787    pub fn try_alloc_fmt(&self, args: fmt::Arguments) -> Result<BumpBox<'a, str>, AllocError> {
1788        self.generic_alloc_fmt(args)
1789    }
1790
1791    #[inline(always)]
1792    pub(crate) fn generic_alloc_fmt<B: ErrorBehavior>(&self, args: fmt::Arguments) -> Result<BumpBox<'a, str>, B> {
1793        if let Some(string) = args.as_str() {
1794            return self.generic_alloc_str(string);
1795        }
1796
1797        let mut string = BumpString::new_in(self);
1798        string.generic_write_fmt(args)?;
1799        Ok(string.into_boxed_str())
1800    }
1801
1802    /// Allocate a `str` from format arguments.
1803    ///
1804    /// This function is designed as a performance improvement over [`alloc_fmt`](Self::alloc_fmt).
1805    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
1806    /// for the temporary string buffer used for the allocation. As a result, that string buffer rarely needs to grow.
1807    ///
1808    /// # Panics
1809    /// Panics if the allocation fails.
1810    ///
1811    /// This technically also panics if the `fmt()` implementation returned an Error,
1812    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1813    /// that should be equivalent to an allocation failure.
1814    ///
1815    /// # Examples
1816    /// ```
1817    /// # use bump_scope::Bump;
1818    /// # let mut bump: Bump = Bump::new();
1819    /// let one = 1;
1820    /// let two = 2;
1821    /// let string = bump.alloc_fmt_mut(format_args!("{one} + {two} = {}", one + two));
1822    ///
1823    /// assert_eq!(string, "1 + 2 = 3");
1824    /// ```
1825    #[inline(always)]
1826    #[cfg(feature = "panic-on-alloc")]
1827    pub fn alloc_fmt_mut(&mut self, args: fmt::Arguments) -> BumpBox<'a, str> {
1828        panic_on_error(self.generic_alloc_fmt_mut(args))
1829    }
1830
1831    /// Allocate a `str` from format arguments.
1832    ///
1833    /// This function is designed as a performance improvement over [`try_alloc_fmt`](Self::try_alloc_fmt).
1834    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
1835    /// for the temporary string buffer used for the allocation. As a result, that string buffer rarely needs to grow.
1836    ///
1837    /// # Errors
1838    /// Errors if the allocation fails.
1839    ///
1840    /// This technically also errors if the `fmt()` implementation returned an Error,
1841    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1842    /// that should be equivalent to an allocation failure.
1843    ///
1844    /// # Examples
1845    /// ```
1846    /// # use bump_scope::Bump;
1847    /// # let mut bump: Bump = Bump::try_new()?;
1848    /// let one = 1;
1849    /// let two = 2;
1850    /// let string = bump.try_alloc_fmt_mut(format_args!("{one} + {two} = {}", one + two))?;
1851    ///
1852    /// assert_eq!(string, "1 + 2 = 3");
1853    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1854    /// ```
1855    #[inline(always)]
1856    pub fn try_alloc_fmt_mut(&mut self, args: fmt::Arguments) -> Result<BumpBox<'a, str>, AllocError> {
1857        self.generic_alloc_fmt_mut(args)
1858    }
1859
1860    #[inline(always)]
1861    pub(crate) fn generic_alloc_fmt_mut<B: ErrorBehavior>(&mut self, args: fmt::Arguments) -> Result<BumpBox<'a, str>, B> {
1862        if let Some(string) = args.as_str() {
1863            return self.generic_alloc_str(string);
1864        }
1865
1866        let mut string = MutBumpString::new_in(self);
1867        string.generic_write_fmt(args)?;
1868        Ok(string.into_boxed_str())
1869    }
1870
1871    /// Allocate a `CStr`.
1872    ///
1873    /// # Panics
1874    /// Panics if the allocation fails.
1875    ///
1876    /// # Examples
1877    /// ```
1878    /// # use bump_scope::Bump;
1879    /// # let bump: Bump = Bump::new();
1880    /// let allocated = bump.alloc_cstr(c"Hello, world!");
1881    /// assert_eq!(allocated, c"Hello, world!");
1882    /// ```
1883    #[inline(always)]
1884    #[cfg(feature = "panic-on-alloc")]
1885    pub fn alloc_cstr(&self, src: &CStr) -> &'a CStr {
1886        panic_on_error(self.generic_alloc_cstr(src))
1887    }
1888
1889    /// Allocate a `CStr`.
1890    ///
1891    /// # Errors
1892    /// Errors if the allocation fails.
1893    ///
1894    /// # Examples
1895    /// ```
1896    /// # use bump_scope::Bump;
1897    /// # let bump: Bump = Bump::try_new()?;
1898    /// let allocated = bump.try_alloc_cstr(c"Hello, world!")?;
1899    /// assert_eq!(allocated, c"Hello, world!");
1900    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1901    /// ```
1902    #[inline(always)]
1903    pub fn try_alloc_cstr(&self, src: &CStr) -> Result<&'a CStr, AllocError> {
1904        self.generic_alloc_cstr(src)
1905    }
1906
1907    #[inline(always)]
1908    pub(crate) fn generic_alloc_cstr<B: ErrorBehavior>(&self, src: &CStr) -> Result<&'a CStr, B> {
1909        let slice = self.generic_alloc_slice_copy(src.to_bytes_with_nul())?.into_ref();
1910
1911        // SAFETY: input is `CStr` so this is too
1912        Ok(unsafe { CStr::from_bytes_with_nul_unchecked(slice) })
1913    }
1914
1915    /// Allocate a `CStr` from a `str`.
1916    ///
1917    /// If `src` contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1918    ///
1919    /// # Panics
1920    /// Panics if the allocation fails.
1921    ///
1922    /// # Examples
1923    /// ```
1924    /// # use bump_scope::Bump;
1925    /// # let bump: Bump = Bump::new();
1926    /// let allocated = bump.alloc_cstr_from_str("Hello, world!");
1927    /// assert_eq!(allocated, c"Hello, world!");
1928    ///
1929    /// let allocated = bump.alloc_cstr_from_str("abc\0def");
1930    /// assert_eq!(allocated, c"abc");
1931    /// ```
1932    #[inline(always)]
1933    #[cfg(feature = "panic-on-alloc")]
1934    pub fn alloc_cstr_from_str(&self, src: &str) -> &'a CStr {
1935        panic_on_error(self.generic_alloc_cstr_from_str(src))
1936    }
1937
1938    /// Allocate a `CStr` from a `str`.
1939    ///
1940    /// If `src` contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1941    ///
1942    /// # Errors
1943    /// Errors if the allocation fails.
1944    ///
1945    /// # Examples
1946    /// ```
1947    /// # use bump_scope::Bump;
1948    /// # let bump: Bump = Bump::try_new()?;
1949    /// let allocated = bump.try_alloc_cstr_from_str("Hello, world!")?;
1950    /// assert_eq!(allocated, c"Hello, world!");
1951    ///
1952    /// let allocated = bump.try_alloc_cstr_from_str("abc\0def")?;
1953    /// assert_eq!(allocated, c"abc");
1954    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1955    /// ```
1956    #[inline(always)]
1957    pub fn try_alloc_cstr_from_str(&self, src: &str) -> Result<&'a CStr, AllocError> {
1958        self.generic_alloc_cstr_from_str(src)
1959    }
1960
1961    #[inline(always)]
1962    pub(crate) fn generic_alloc_cstr_from_str<B: ErrorBehavior>(&self, src: &str) -> Result<&'a CStr, B> {
1963        let src = src.as_bytes();
1964
1965        if let Some(nul) = src.iter().position(|&c| c == b'\0') {
1966            let bytes_with_nul = unsafe { src.get_unchecked(..nul + 1) };
1967            let cstr = unsafe { CStr::from_bytes_with_nul_unchecked(bytes_with_nul) };
1968            self.generic_alloc_cstr(cstr)
1969        } else {
1970            // `src` contains no null
1971            let dst = self.do_alloc_slice(src.len() + 1)?;
1972
1973            unsafe {
1974                core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_ptr(), src.len());
1975                dst.as_ptr().add(src.len()).write(0);
1976
1977                let bytes = core::slice::from_raw_parts(dst.as_ptr(), src.len() + 1);
1978                Ok(CStr::from_bytes_with_nul_unchecked(bytes))
1979            }
1980        }
1981    }
1982
1983    /// Allocate a `CStr` from format arguments.
1984    ///
1985    /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1986    ///
1987    /// If you have a `&mut self` you can use [`alloc_cstr_fmt_mut`](Self::alloc_cstr_fmt_mut)
1988    /// instead for better performance.
1989    ///
1990    /// # Panics
1991    /// Panics if the allocation fails.
1992    ///
1993    /// This technically also panics if the `fmt()` implementation returned an Error,
1994    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
1995    /// that should be equivalent to an allocation failure.
1996    ///
1997    /// # Examples
1998    /// ```
1999    /// # use bump_scope::Bump;
2000    /// # let bump: Bump = Bump::new();
2001    /// let one = 1;
2002    /// let two = 2;
2003    /// let string = bump.alloc_cstr_fmt(format_args!("{one} + {two} = {}", one + two));
2004    /// assert_eq!(string, c"1 + 2 = 3");
2005    ///
2006    /// let one = bump.alloc_cstr_fmt(format_args!("{one}\0{two}"));
2007    /// assert_eq!(one, c"1");
2008    /// ```
2009    #[inline(always)]
2010    #[cfg(feature = "panic-on-alloc")]
2011    pub fn alloc_cstr_fmt(&self, args: fmt::Arguments) -> &'a CStr {
2012        panic_on_error(self.generic_alloc_cstr_fmt(args))
2013    }
2014
2015    /// Allocate a `CStr` from format arguments.
2016    ///
2017    /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
2018    ///
2019    /// If you have a `&mut self` you can use [`try_alloc_cstr_fmt_mut`](Self::try_alloc_cstr_fmt_mut)
2020    /// instead for better performance.
2021    ///
2022    /// # Errors
2023    /// Errors if the allocation fails.
2024    ///
2025    /// This technically also errors if the `fmt()` implementation returned an Error,
2026    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
2027    /// that should be equivalent to an allocation failure.
2028    ///
2029    /// # Examples
2030    /// ```
2031    /// # use bump_scope::Bump;
2032    /// # let bump: Bump = Bump::try_new()?;
2033    /// let one = 1;
2034    /// let two = 2;
2035    /// let string = bump.try_alloc_cstr_fmt(format_args!("{one} + {two} = {}", one + two))?;
2036    /// assert_eq!(string, c"1 + 2 = 3");
2037    ///
2038    /// let one = bump.try_alloc_cstr_fmt(format_args!("{one}\0{two}"))?;
2039    /// assert_eq!(one, c"1");
2040    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2041    /// ```
2042    #[inline(always)]
2043    pub fn try_alloc_cstr_fmt(&self, args: fmt::Arguments) -> Result<&'a CStr, AllocError> {
2044        self.generic_alloc_cstr_fmt(args)
2045    }
2046
2047    #[inline(always)]
2048    pub(crate) fn generic_alloc_cstr_fmt<B: ErrorBehavior>(&self, args: fmt::Arguments) -> Result<&'a CStr, B> {
2049        if let Some(string) = args.as_str() {
2050            return self.generic_alloc_cstr_from_str(string);
2051        }
2052
2053        let mut string = BumpString::new_in(self);
2054        string.generic_write_fmt(args)?;
2055        string.generic_into_cstr()
2056    }
2057
2058    /// Allocate a `CStr` from format arguments.
2059    ///
2060    /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
2061    ///
2062    /// This function is designed as a performance improvement over [`alloc_cstr_fmt`](Self::alloc_cstr_fmt).
2063    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
2064    /// for the temporary string buffer used for the allocation. As a result, that string buffer rarely needs to grow.
2065    ///
2066    /// # Panics
2067    /// Panics if the allocation fails.
2068    ///
2069    /// This technically also panics if the `fmt()` implementation returned an Error,
2070    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
2071    /// that should be equivalent to an allocation failure.
2072    ///
2073    /// # Examples
2074    /// ```
2075    /// # use bump_scope::Bump;
2076    /// # let mut bump: Bump = Bump::new();
2077    /// let one = 1;
2078    /// let two = 2;
2079    /// let string = bump.alloc_cstr_fmt_mut(format_args!("{one} + {two} = {}", one + two));
2080    /// assert_eq!(string, c"1 + 2 = 3");
2081    ///
2082    /// let one = bump.alloc_cstr_fmt_mut(format_args!("{one}\0{two}"));
2083    /// assert_eq!(one, c"1");
2084    /// ```
2085    #[inline(always)]
2086    #[cfg(feature = "panic-on-alloc")]
2087    pub fn alloc_cstr_fmt_mut(&mut self, args: fmt::Arguments) -> &'a CStr {
2088        panic_on_error(self.generic_alloc_cstr_fmt_mut(args))
2089    }
2090
2091    /// Allocate a `CStr` from format arguments.
2092    ///
2093    /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
2094    ///
2095    /// This function is designed as a performance improvement over [`try_alloc_cstr_fmt`](Self::try_alloc_cstr_fmt).
2096    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
2097    /// for the temporary string buffer used for the allocation. As a result, that string buffer rarely needs to grow.
2098    ///
2099    /// # Errors
2100    /// Errors if the allocation fails.
2101    ///
2102    /// This technically also errors if the `fmt()` implementation returned an Error,
2103    /// but since [`fmt()` implementors should only error when writing to the stream fails](core::fmt::Error),
2104    /// that should be equivalent to an allocation failure.
2105    ///
2106    /// # Examples
2107    /// ```
2108    /// # use bump_scope::Bump;
2109    /// # let mut bump: Bump = Bump::try_new()?;
2110    /// let one = 1;
2111    /// let two = 2;
2112    /// let string = bump.try_alloc_cstr_fmt_mut(format_args!("{one} + {two} = {}", one + two))?;
2113    /// assert_eq!(string, c"1 + 2 = 3");
2114    ///
2115    /// let one = bump.try_alloc_cstr_fmt_mut(format_args!("{one}\0{two}"))?;
2116    /// assert_eq!(one, c"1");
2117    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2118    /// ```
2119    #[inline(always)]
2120    pub fn try_alloc_cstr_fmt_mut(&mut self, args: fmt::Arguments) -> Result<&'a CStr, AllocError> {
2121        self.generic_alloc_cstr_fmt_mut(args)
2122    }
2123
2124    #[inline(always)]
2125    pub(crate) fn generic_alloc_cstr_fmt_mut<B: ErrorBehavior>(&mut self, args: fmt::Arguments) -> Result<&'a CStr, B> {
2126        if let Some(string) = args.as_str() {
2127            return self.generic_alloc_cstr_from_str(string);
2128        }
2129
2130        let mut string = MutBumpString::new_in(self);
2131        string.generic_write_fmt(args)?;
2132        string.generic_into_cstr()
2133    }
2134
2135    /// Allocate elements of an iterator into a slice.
2136    ///
2137    /// If you have an `impl ExactSizeIterator` then you can use [`alloc_iter_exact`] instead for better performance.
2138    ///
2139    /// If `iter` is not an `ExactSizeIterator` but you have a `&mut self` you can still get somewhat better performance by using [`alloc_iter_mut`].
2140    ///
2141    /// [`alloc_iter_exact`]: Self::alloc_iter_exact
2142    /// [`alloc_iter_mut`]: Self::alloc_iter_mut
2143    ///
2144    /// # Panics
2145    /// Panics if the allocation fails.
2146    ///
2147    /// # Examples
2148    /// ```
2149    /// # use bump_scope::Bump;
2150    /// # let bump: Bump = Bump::new();
2151    /// let slice = bump.alloc_iter([1, 2, 3]);
2152    /// assert_eq!(slice, [1, 2, 3]);
2153    /// ```
2154    #[inline(always)]
2155    #[cfg(feature = "panic-on-alloc")]
2156    pub fn alloc_iter<T>(&self, iter: impl IntoIterator<Item = T>) -> BumpBox<'a, [T]> {
2157        panic_on_error(self.generic_alloc_iter(iter))
2158    }
2159
2160    /// Allocate elements of an iterator into a slice.
2161    ///
2162    /// If you have an `impl ExactSizeIterator` then you can use [`try_alloc_iter_exact`] instead for better performance.
2163    ///
2164    /// 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`].
2165    ///
2166    /// [`try_alloc_iter_exact`]: Self::try_alloc_iter_exact
2167    /// [`try_alloc_iter_mut`]: Self::try_alloc_iter_mut
2168    ///
2169    /// # Errors
2170    /// Errors if the allocation fails.
2171    ///
2172    /// # Examples
2173    /// ```
2174    /// # use bump_scope::Bump;
2175    /// # let bump: Bump = Bump::try_new()?;
2176    /// let slice = bump.try_alloc_iter([1, 2, 3])?;
2177    /// assert_eq!(slice, [1, 2, 3]);
2178    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2179    /// ```
2180    #[inline(always)]
2181    pub fn try_alloc_iter<T>(&self, iter: impl IntoIterator<Item = T>) -> Result<BumpBox<'a, [T]>, AllocError> {
2182        self.generic_alloc_iter(iter)
2183    }
2184
2185    #[inline(always)]
2186    pub(crate) fn generic_alloc_iter<B: ErrorBehavior, T>(
2187        &self,
2188        iter: impl IntoIterator<Item = T>,
2189    ) -> Result<BumpBox<'a, [T]>, B> {
2190        let iter = iter.into_iter();
2191        let capacity = iter.size_hint().0;
2192
2193        let mut vec = BumpVec::<T, &Self>::generic_with_capacity_in(capacity, self)?;
2194
2195        for value in iter {
2196            vec.generic_push(value)?;
2197        }
2198
2199        Ok(vec.into_boxed_slice())
2200    }
2201
2202    /// Allocate elements of an `ExactSizeIterator` into a slice.
2203    ///
2204    /// # Panics
2205    /// Panics if the allocation fails.
2206    ///
2207    /// # Examples
2208    /// ```
2209    /// # use bump_scope::Bump;
2210    /// # let bump: Bump = Bump::new();
2211    /// let slice = bump.alloc_iter_exact([1, 2, 3]);
2212    /// assert_eq!(slice, [1, 2, 3]);
2213    /// ```
2214    #[inline(always)]
2215    #[cfg(feature = "panic-on-alloc")]
2216    pub fn alloc_iter_exact<T, I>(&self, iter: impl IntoIterator<Item = T, IntoIter = I>) -> BumpBox<'a, [T]>
2217    where
2218        I: ExactSizeIterator<Item = T>,
2219    {
2220        panic_on_error(self.generic_alloc_iter_exact(iter))
2221    }
2222
2223    /// Allocate elements of an `ExactSizeIterator` into a slice.
2224    ///
2225    /// # Errors
2226    /// Errors if the allocation fails.
2227    ///
2228    /// # Examples
2229    /// ```
2230    /// # use bump_scope::Bump;
2231    /// # let bump: Bump = Bump::try_new()?;
2232    /// let slice = bump.try_alloc_iter_exact([1, 2, 3])?;
2233    /// assert_eq!(slice, [1, 2, 3]);
2234    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2235    /// ```
2236    #[inline(always)]
2237    pub fn try_alloc_iter_exact<T, I>(
2238        &self,
2239        iter: impl IntoIterator<Item = T, IntoIter = I>,
2240    ) -> Result<BumpBox<'a, [T]>, AllocError>
2241    where
2242        I: ExactSizeIterator<Item = T>,
2243    {
2244        self.generic_alloc_iter_exact(iter)
2245    }
2246
2247    #[inline(always)]
2248    pub(crate) fn generic_alloc_iter_exact<B: ErrorBehavior, T, I>(
2249        &self,
2250        iter: impl IntoIterator<Item = T, IntoIter = I>,
2251    ) -> Result<BumpBox<'a, [T]>, B>
2252    where
2253        I: ExactSizeIterator<Item = T>,
2254    {
2255        let mut iter = iter.into_iter();
2256        let len = iter.len();
2257
2258        let mut vec = BumpVec::<T, &Self>::generic_with_capacity_in(len, self)?;
2259
2260        while vec.len() != vec.capacity() {
2261            match iter.next() {
2262                // SAFETY: we checked above that `len != capacity`, so there is space
2263                Some(value) => unsafe { vec.push_unchecked(value) },
2264                None => break,
2265            }
2266        }
2267
2268        Ok(vec.into_fixed_vec().into_boxed_slice())
2269    }
2270
2271    /// Allocate elements of an iterator into a slice.
2272    ///
2273    /// This function is designed as a performance improvement over [`alloc_iter`](Self::alloc_iter).
2274    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
2275    /// for the temporary vector used for the allocation. As a result, that vector rarely needs to grow.
2276    ///
2277    /// When bumping downwards, prefer [`alloc_iter_mut_rev`](Self::alloc_iter_mut_rev) instead.
2278    ///
2279    /// # Panics
2280    /// Panics if the allocation fails.
2281    ///
2282    /// # Examples
2283    /// ```
2284    /// # use bump_scope::Bump;
2285    /// # let mut bump: Bump = Bump::new();
2286    /// let slice = bump.alloc_iter_mut([1, 2, 3]);
2287    /// assert_eq!(slice, [1, 2, 3]);
2288    /// ```
2289    #[inline(always)]
2290    #[cfg(feature = "panic-on-alloc")]
2291    pub fn alloc_iter_mut<T>(&mut self, iter: impl IntoIterator<Item = T>) -> BumpBox<'a, [T]> {
2292        panic_on_error(self.generic_alloc_iter_mut(iter))
2293    }
2294
2295    /// Allocate elements of an iterator into a slice.
2296    ///
2297    /// This function is designed as a performance improvement over [`try_alloc_iter`](Self::try_alloc_iter).
2298    /// By taking `self` as `&mut`, it can use the entire remaining chunk space as the capacity
2299    /// for the temporary vector used for the allocation. As a result, that vector rarely needs to grow.
2300    ///
2301    /// When bumping downwards, prefer [`alloc_iter_mut_rev`](Self::alloc_iter_mut_rev) instead.
2302    ///
2303    /// # Errors
2304    /// Errors if the allocation fails.
2305    ///
2306    /// # Examples
2307    /// ```
2308    /// # use bump_scope::Bump;
2309    /// # let mut bump: Bump = Bump::try_new()?;
2310    /// let slice = bump.try_alloc_iter_mut([1, 2, 3])?;
2311    /// assert_eq!(slice, [1, 2, 3]);
2312    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2313    /// ```
2314    #[inline(always)]
2315    pub fn try_alloc_iter_mut<T>(&mut self, iter: impl IntoIterator<Item = T>) -> Result<BumpBox<'a, [T]>, AllocError> {
2316        self.generic_alloc_iter_mut(iter)
2317    }
2318
2319    #[inline(always)]
2320    pub(crate) fn generic_alloc_iter_mut<B: ErrorBehavior, T>(
2321        &mut self,
2322        iter: impl IntoIterator<Item = T>,
2323    ) -> Result<BumpBox<'a, [T]>, B> {
2324        let iter = iter.into_iter();
2325        let capacity = iter.size_hint().0;
2326
2327        let mut vec = MutBumpVec::<T, &mut Self>::generic_with_capacity_in(capacity, self)?;
2328
2329        for value in iter {
2330            vec.generic_push(value)?;
2331        }
2332
2333        Ok(vec.into_boxed_slice())
2334    }
2335
2336    /// Allocate elements of an iterator into a slice in reverse order.
2337    ///
2338    /// Compared to [`alloc_iter_mut`] this function is more performant
2339    /// for downwards bumping allocators as the allocation for the vector can be shrunk in place
2340    /// without any `ptr::copy`.
2341    ///
2342    /// The reverse is true when upwards allocating. In that case it's better to use [`alloc_iter_mut`] to prevent
2343    /// the `ptr::copy`.
2344    ///
2345    /// [`alloc_iter_mut`]: Self::alloc_iter_mut
2346    ///
2347    /// # Panics
2348    /// Panics if the allocation fails.
2349    ///
2350    /// # Examples
2351    /// ```
2352    /// # use bump_scope::Bump;
2353    /// # let mut bump: Bump = Bump::new();
2354    /// let slice = bump.alloc_iter_mut_rev([1, 2, 3]);
2355    /// assert_eq!(slice, [3, 2, 1]);
2356    /// ```
2357    #[inline(always)]
2358    #[cfg(feature = "panic-on-alloc")]
2359    pub fn alloc_iter_mut_rev<T>(&mut self, iter: impl IntoIterator<Item = T>) -> BumpBox<'a, [T]> {
2360        panic_on_error(self.generic_alloc_iter_mut_rev(iter))
2361    }
2362
2363    /// Allocate elements of an iterator into a slice in reverse order.
2364    ///
2365    /// Compared to [`try_alloc_iter_mut`] this function is more performant
2366    /// for downwards bumping allocators as the allocation for the vector can be shrunk in place
2367    /// without any `ptr::copy`.
2368    ///
2369    /// The reverse is true when upwards allocating. In that case it's better to use [`try_alloc_iter_mut`] to prevent
2370    /// the `ptr::copy`.
2371    ///
2372    /// [`try_alloc_iter_mut`]: Self::try_alloc_iter_mut
2373    ///
2374    /// # Errors
2375    /// Errors if the allocation fails.
2376    ///
2377    /// # Examples
2378    /// ```
2379    /// # use bump_scope::Bump;
2380    /// # let mut bump: Bump = Bump::try_new()?;
2381    /// let slice = bump.try_alloc_iter_mut_rev([1, 2, 3])?;
2382    /// assert_eq!(slice, [3, 2, 1]);
2383    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2384    /// ```
2385    #[inline(always)]
2386    pub fn try_alloc_iter_mut_rev<T>(&mut self, iter: impl IntoIterator<Item = T>) -> Result<BumpBox<'a, [T]>, AllocError> {
2387        self.generic_alloc_iter_mut_rev(iter)
2388    }
2389
2390    #[inline(always)]
2391    pub(crate) fn generic_alloc_iter_mut_rev<B: ErrorBehavior, T>(
2392        &mut self,
2393        iter: impl IntoIterator<Item = T>,
2394    ) -> Result<BumpBox<'a, [T]>, B> {
2395        let iter = iter.into_iter();
2396        let capacity = iter.size_hint().0;
2397
2398        let mut vec = MutBumpVecRev::<T, &mut Self>::generic_with_capacity_in(capacity, self)?;
2399
2400        for value in iter {
2401            vec.generic_push(value)?;
2402        }
2403
2404        Ok(vec.into_boxed_slice())
2405    }
2406
2407    /// Allocate an unitialized object.
2408    ///
2409    /// You can safely initialize the object with [`init`](BumpBox::init) or unsafely with [`assume_init`](BumpBox::assume_init).
2410    ///
2411    /// # Panics
2412    /// Panics if the allocation fails.
2413    ///
2414    /// # Examples
2415    /// Safely:
2416    /// ```
2417    /// # use bump_scope::Bump;
2418    /// # let bump: Bump = Bump::new();
2419    /// let uninit = bump.alloc_uninit();
2420    ///
2421    /// let five = uninit.init(5);
2422    ///
2423    /// assert_eq!(*five, 5)
2424    /// ```
2425    ///
2426    /// Unsafely:
2427    /// ```
2428    /// # use bump_scope::Bump;
2429    /// # let bump: Bump = Bump::new();
2430    /// let mut uninit = bump.alloc_uninit();
2431    ///
2432    /// let five = unsafe {
2433    ///     uninit.write(5);
2434    ///     uninit.assume_init()
2435    /// };
2436    ///
2437    /// assert_eq!(*five, 5)
2438    /// ```
2439    #[inline(always)]
2440    #[cfg(feature = "panic-on-alloc")]
2441    pub fn alloc_uninit<T>(&self) -> BumpBox<'a, MaybeUninit<T>> {
2442        panic_on_error(self.generic_alloc_uninit())
2443    }
2444
2445    /// Allocate an unitialized object.
2446    ///
2447    /// You can safely initialize the object with [`init`](BumpBox::init) or unsafely with [`assume_init`](BumpBox::assume_init).
2448    ///
2449    /// # Errors
2450    /// Errors if the allocation fails.
2451    ///
2452    /// # Examples
2453    /// Safely:
2454    /// ```
2455    /// # use bump_scope::Bump;
2456    /// # let bump: Bump = Bump::new();
2457    /// let uninit = bump.try_alloc_uninit()?;
2458    ///
2459    /// let five = uninit.init(5);
2460    ///
2461    /// assert_eq!(*five, 5);
2462    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2463    /// ```
2464    ///
2465    /// Unsafely:
2466    /// ```
2467    /// # use bump_scope::Bump;
2468    /// # let bump: Bump = Bump::try_new()?;
2469    /// let mut uninit = bump.try_alloc_uninit()?;
2470    ///
2471    /// let five = unsafe {
2472    ///     uninit.write(5);
2473    ///     uninit.assume_init()
2474    /// };
2475    ///
2476    /// assert_eq!(*five, 5);
2477    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2478    /// ```
2479    #[inline(always)]
2480    pub fn try_alloc_uninit<T>(&self) -> Result<BumpBox<'a, MaybeUninit<T>>, AllocError> {
2481        self.generic_alloc_uninit()
2482    }
2483
2484    #[inline(always)]
2485    pub(crate) fn generic_alloc_uninit<B: ErrorBehavior, T>(&self) -> Result<BumpBox<'a, MaybeUninit<T>>, B> {
2486        if T::IS_ZST {
2487            return Ok(BumpBox::zst(MaybeUninit::uninit()));
2488        }
2489
2490        let ptr = self.do_alloc_sized::<B, T>()?.cast::<MaybeUninit<T>>();
2491        unsafe { Ok(BumpBox::from_raw(ptr)) }
2492    }
2493
2494    /// Allocate an unitialized object slice.
2495    ///
2496    /// You can safely initialize the object with
2497    /// [`init_fill`](BumpBox::init_fill),
2498    /// [`init_fill_with`](BumpBox::init_fill_with),
2499    /// [`init_copy`](BumpBox::init_copy),
2500    /// [`init_clone`](BumpBox::init_clone),
2501    /// [`init_zeroed`](crate::zerocopy_08::InitZeroed::init_zeroed) or unsafely with
2502    /// [`assume_init`](BumpBox::assume_init).
2503    ///
2504    /// # Panics
2505    /// Panics if the allocation fails.
2506    ///
2507    /// # Examples
2508    /// Safely:
2509    /// ```
2510    /// # use bump_scope::Bump;
2511    /// # let bump: Bump = Bump::new();
2512    /// let uninit = bump.alloc_uninit_slice(3);
2513    ///
2514    /// let values = uninit.init_copy(&[1, 2, 3]);
2515    ///
2516    /// assert_eq!(values, [1, 2, 3])
2517    /// ```
2518    ///
2519    /// Unsafely:
2520    /// ```
2521    /// # use bump_scope::Bump;
2522    /// # let bump: Bump = Bump::new();
2523    /// let mut uninit = bump.alloc_uninit_slice(3);
2524    ///
2525    /// let values = unsafe {
2526    ///     uninit[0].write(1);
2527    ///     uninit[1].write(2);
2528    ///     uninit[2].write(3);
2529    ///
2530    ///     uninit.assume_init()
2531    /// };
2532    ///
2533    /// assert_eq!(values, [1, 2, 3]);
2534    /// ```
2535    #[inline(always)]
2536    #[cfg(feature = "panic-on-alloc")]
2537    pub fn alloc_uninit_slice<T>(&self, len: usize) -> BumpBox<'a, [MaybeUninit<T>]> {
2538        panic_on_error(self.generic_alloc_uninit_slice(len))
2539    }
2540
2541    /// Allocate an unitialized object slice.
2542    ///
2543    /// You can safely initialize the object with
2544    /// [`init_fill`](BumpBox::init_fill),
2545    /// [`init_fill_with`](BumpBox::init_fill_with),
2546    /// [`init_copy`](BumpBox::init_copy),
2547    /// [`init_clone`](BumpBox::init_clone),
2548    /// [`init_zeroed`](crate::zerocopy_08::InitZeroed::init_zeroed) or unsafely with
2549    /// [`assume_init`](BumpBox::assume_init).
2550    ///
2551    /// # Errors
2552    /// Errors if the allocation fails.
2553    ///
2554    /// # Examples
2555    /// Safely:
2556    /// ```
2557    /// # use bump_scope::Bump;
2558    /// # let bump: Bump = Bump::new();
2559    /// let uninit = bump.try_alloc_uninit_slice(3)?;
2560    ///
2561    /// let values = uninit.init_copy(&[1, 2, 3]);
2562    ///
2563    /// assert_eq!(values, [1, 2, 3]);
2564    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2565    /// ```
2566    ///
2567    /// Unsafely:
2568    /// ```
2569    /// # use bump_scope::Bump;
2570    /// # let bump: Bump = Bump::try_new()?;
2571    /// let mut uninit = bump.try_alloc_uninit_slice(3)?;
2572    ///
2573    /// let values = unsafe {
2574    ///     uninit[0].write(1);
2575    ///     uninit[1].write(2);
2576    ///     uninit[2].write(3);
2577    ///
2578    ///     uninit.assume_init()
2579    /// };
2580    ///
2581    /// assert_eq!(values, [1, 2, 3]);
2582    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2583    /// ```
2584    #[inline(always)]
2585    pub fn try_alloc_uninit_slice<T>(&self, len: usize) -> Result<BumpBox<'a, [MaybeUninit<T>]>, AllocError> {
2586        self.generic_alloc_uninit_slice(len)
2587    }
2588
2589    #[inline(always)]
2590    pub(crate) fn generic_alloc_uninit_slice<B: ErrorBehavior, T>(
2591        &self,
2592        len: usize,
2593    ) -> Result<BumpBox<'a, [MaybeUninit<T>]>, B> {
2594        if T::IS_ZST {
2595            return Ok(BumpBox::uninit_zst_slice(len));
2596        }
2597
2598        let ptr = self.do_alloc_slice::<B, T>(len)?.cast::<MaybeUninit<T>>();
2599
2600        unsafe {
2601            let ptr = NonNull::slice_from_raw_parts(ptr, len);
2602            Ok(BumpBox::from_raw(ptr))
2603        }
2604    }
2605
2606    /// Allocate an unitialized object slice.
2607    ///
2608    /// You can safely initialize the object with
2609    /// [`init_fill`](BumpBox::init_fill),
2610    /// [`init_fill_with`](BumpBox::init_fill_with),
2611    /// [`init_copy`](BumpBox::init_copy),
2612    /// [`init_clone`](BumpBox::init_clone),
2613    /// [`init_zeroed`](crate::zerocopy_08::InitZeroed::init_zeroed) or unsafely with
2614    /// [`assume_init`](BumpBox::assume_init).
2615    ///
2616    /// This is just like [`alloc_uninit_slice`](Self::alloc_uninit_slice) but uses a `slice` to provide the `len`.
2617    /// This avoids a check for a valid layout. The elements of `slice` are irrelevant.
2618    ///
2619    /// # Panics
2620    /// Panics if the allocation fails.
2621    ///
2622    /// # Examples
2623    /// ```
2624    /// # use bump_scope::Bump;
2625    /// # let bump: Bump = Bump::new();
2626    /// let slice = &[1, 2, 3];
2627    /// let uninit_slice = bump.alloc_uninit_slice_for(slice);
2628    /// assert_eq!(uninit_slice.len(), 3);
2629    /// ```
2630    #[inline(always)]
2631    #[cfg(feature = "panic-on-alloc")]
2632    pub fn alloc_uninit_slice_for<T>(&self, slice: &[T]) -> BumpBox<'a, [MaybeUninit<T>]> {
2633        panic_on_error(self.generic_alloc_uninit_slice_for(slice))
2634    }
2635
2636    /// Allocate an unitialized object slice.
2637    ///
2638    /// You can safely initialize the object with
2639    /// [`init_fill`](BumpBox::init_fill),
2640    /// [`init_fill_with`](BumpBox::init_fill_with),
2641    /// [`init_copy`](BumpBox::init_copy),
2642    /// [`init_clone`](BumpBox::init_clone),
2643    /// [`init_zeroed`](crate::zerocopy_08::InitZeroed::init_zeroed) or unsafely with
2644    /// [`assume_init`](BumpBox::assume_init).
2645    ///
2646    /// This is just like [`try_alloc_uninit_slice`](Self::try_alloc_uninit_slice) but uses a `slice` to provide the `len`.
2647    /// This avoids a check for a valid layout. The elements of `slice` are irrelevant.
2648    ///
2649    /// # Errors
2650    /// Errors if the allocation fails.
2651    ///
2652    /// # Examples
2653    /// ```
2654    /// # use bump_scope::Bump;
2655    /// # let bump: Bump = Bump::try_new()?;
2656    /// let slice = &[1, 2, 3];
2657    /// let uninit_slice = bump.try_alloc_uninit_slice_for(slice)?;
2658    /// assert_eq!(uninit_slice.len(), 3);
2659    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2660    /// ```
2661    #[inline(always)]
2662    pub fn try_alloc_uninit_slice_for<T>(&self, slice: &[T]) -> Result<BumpBox<'a, [MaybeUninit<T>]>, AllocError> {
2663        self.generic_alloc_uninit_slice_for(slice)
2664    }
2665
2666    #[inline(always)]
2667    pub(crate) fn generic_alloc_uninit_slice_for<B: ErrorBehavior, T>(
2668        &self,
2669        slice: &[T],
2670    ) -> Result<BumpBox<'a, [MaybeUninit<T>]>, B> {
2671        if T::IS_ZST {
2672            return Ok(BumpBox::uninit_zst_slice(slice.len()));
2673        }
2674
2675        let ptr = self.do_alloc_slice_for::<B, T>(slice)?.cast::<MaybeUninit<T>>();
2676
2677        unsafe {
2678            let ptr = NonNull::slice_from_raw_parts(ptr, slice.len());
2679            Ok(BumpBox::from_raw(ptr))
2680        }
2681    }
2682
2683    /// Allocate a [`FixedBumpVec`] with the given `capacity`.
2684    ///
2685    /// # Panics
2686    /// Panics if the allocation fails.
2687    ///
2688    /// # Examples
2689    /// ```
2690    /// # use bump_scope::Bump;
2691    /// # let bump: Bump = Bump::new();
2692    /// # #[expect(deprecated)]
2693    /// let mut values = bump.alloc_fixed_vec(3);
2694    /// values.push(1);
2695    /// values.push(2);
2696    /// values.push(3);
2697    /// assert_eq!(values, [1, 2, 3])
2698    /// ```
2699    #[doc(hidden)]
2700    #[deprecated = "use `FixedBumpVec::with_capacity_in()` instead"]
2701    #[inline(always)]
2702    #[cfg(feature = "panic-on-alloc")]
2703    pub fn alloc_fixed_vec<T>(&self, capacity: usize) -> FixedBumpVec<'a, T> {
2704        panic_on_error(self.generic_alloc_fixed_vec(capacity))
2705    }
2706
2707    /// Allocate a [`FixedBumpVec`] with the given `capacity`.
2708    ///
2709    /// # Errors
2710    /// Errors if the allocation fails.
2711    ///
2712    /// # Examples
2713    /// ```
2714    /// # use bump_scope::Bump;
2715    /// # let bump: Bump = Bump::try_new()?;
2716    /// # #[expect(deprecated)]
2717    /// let mut values = bump.try_alloc_fixed_vec(3)?;
2718    /// values.push(1);
2719    /// values.push(2);
2720    /// values.push(3);
2721    /// assert_eq!(values, [1, 2, 3]);
2722    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2723    /// ```
2724    #[doc(hidden)]
2725    #[deprecated = "use `FixedBumpVec::try_with_capacity_in()` instead"]
2726    #[inline(always)]
2727    pub fn try_alloc_fixed_vec<T>(&self, capacity: usize) -> Result<FixedBumpVec<'a, T>, AllocError> {
2728        self.generic_alloc_fixed_vec(capacity)
2729    }
2730
2731    #[inline(always)]
2732    pub(crate) fn generic_alloc_fixed_vec<B: ErrorBehavior, T>(&self, capacity: usize) -> Result<FixedBumpVec<'a, T>, B> {
2733        Ok(FixedBumpVec::from_uninit(self.generic_alloc_uninit_slice(capacity)?))
2734    }
2735
2736    /// Allocate a [`FixedBumpString`] with the given `capacity` in bytes.
2737    ///
2738    /// # Panics
2739    /// Panics if the allocation fails.
2740    ///
2741    /// # Examples
2742    /// ```
2743    /// # use bump_scope::Bump;
2744    /// # let bump: Bump = Bump::new();
2745    /// # #[expect(deprecated)]
2746    /// let mut string = bump.alloc_fixed_string(13);
2747    /// string.push_str("Hello,");
2748    /// string.push_str(" world!");
2749    /// assert_eq!(string, "Hello, world!");
2750    /// ```
2751    #[doc(hidden)]
2752    #[deprecated = "use `FixedBumpString::with_capacity_in()` instead"]
2753    #[inline(always)]
2754    #[cfg(feature = "panic-on-alloc")]
2755    pub fn alloc_fixed_string(&self, capacity: usize) -> FixedBumpString<'a> {
2756        panic_on_error(self.generic_alloc_fixed_string(capacity))
2757    }
2758
2759    /// Allocate a [`FixedBumpString`] with the given `capacity` in bytes.
2760    ///
2761    /// # Errors
2762    /// Errors if the allocation fails.
2763    ///
2764    /// # Examples
2765    /// ```
2766    /// # use bump_scope::Bump;
2767    /// # let bump: Bump = Bump::try_new()?;
2768    /// # #[expect(deprecated)]
2769    /// let mut string = bump.try_alloc_fixed_string(13)?;
2770    /// string.push_str("Hello,");
2771    /// string.push_str(" world!");
2772    /// assert_eq!(string, "Hello, world!");
2773    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2774    /// ```
2775    #[doc(hidden)]
2776    #[deprecated = "use `FixedBumpString::try_with_capacity_in()` instead"]
2777    #[inline(always)]
2778    pub fn try_alloc_fixed_string(&self, capacity: usize) -> Result<FixedBumpString<'a>, AllocError> {
2779        self.generic_alloc_fixed_string(capacity)
2780    }
2781
2782    #[inline(always)]
2783    pub(crate) fn generic_alloc_fixed_string<B: ErrorBehavior>(&self, capacity: usize) -> Result<FixedBumpString<'a>, B> {
2784        Ok(FixedBumpString::from_uninit(self.generic_alloc_uninit_slice(capacity)?))
2785    }
2786
2787    /// Allocates memory as described by the given `Layout`.
2788    ///
2789    /// # Panics
2790    /// Panics if the allocation fails.
2791    #[inline(always)]
2792    #[cfg(feature = "panic-on-alloc")]
2793    pub fn alloc_layout(&self, layout: Layout) -> NonNull<u8> {
2794        panic_on_error(self.generic_alloc_layout(layout))
2795    }
2796
2797    /// Allocates memory as described by the given `Layout`.
2798    ///
2799    /// # Errors
2800    /// Errors if the allocation fails.
2801    #[inline(always)]
2802    pub fn try_alloc_layout(&self, layout: Layout) -> Result<NonNull<u8>, AllocError> {
2803        self.generic_alloc_layout(layout)
2804    }
2805
2806    #[inline(always)]
2807    pub(crate) fn generic_alloc_layout<B: ErrorBehavior>(&self, layout: Layout) -> Result<NonNull<u8>, B> {
2808        match self.chunk.get().alloc(MinimumAlignment::<MIN_ALIGN>, CustomLayout(layout)) {
2809            Some(ptr) => Ok(ptr),
2810            None => self.alloc_in_another_chunk(layout),
2811        }
2812    }
2813
2814    /// Drops an allocated value and attempts to free its memory.
2815    ///
2816    /// The memory can only be freed if this is the last allocation.
2817    ///
2818    /// # Examples
2819    /// ```
2820    /// # use bump_scope::Bump;
2821    /// # let bump: Bump = Bump::new();
2822    /// let boxed = bump.alloc(3i32);
2823    /// assert_eq!(bump.stats().allocated(), 4);
2824    /// bump.dealloc(boxed);
2825    /// assert_eq!(bump.stats().allocated(), 0);
2826    /// ```
2827    #[inline(always)]
2828    pub fn dealloc<T: ?Sized>(&self, boxed: BumpBox<T>) {
2829        let layout = Layout::for_value::<T>(&boxed);
2830        let ptr = boxed.into_raw();
2831
2832        unsafe {
2833            ptr.drop_in_place();
2834            self.deallocate(ptr.cast(), layout);
2835        }
2836    }
2837
2838    /// Reserves capacity for at least `additional` more bytes to be bump allocated.
2839    /// The bump allocator may reserve more space to avoid frequent reallocations.
2840    /// After calling `reserve_bytes`, <code>self.[stats](Self::stats)().[remaining](Stats::remaining)()</code> will be greater than or equal to
2841    /// `additional`. Does nothing if the capacity is already sufficient.
2842    ///
2843    /// Note that these additional bytes are not necessarily in one contiguous region but
2844    /// might be spread out among many chunks.
2845    ///
2846    /// # Panics
2847    /// Panics if the allocation fails.
2848    ///
2849    /// # Examples
2850    /// ```
2851    /// # use bump_scope::Bump;
2852    /// let bump: Bump = Bump::new();
2853    /// assert!(bump.stats().capacity() < 4096);
2854    ///
2855    /// bump.reserve_bytes(4096);
2856    /// assert!(bump.stats().capacity() >= 4096);
2857    /// ```
2858    #[inline(always)]
2859    #[cfg(feature = "panic-on-alloc")]
2860    pub fn reserve_bytes(&self, additional: usize) {
2861        panic_on_error(self.generic_reserve_bytes(additional));
2862    }
2863
2864    /// Reserves capacity for at least `additional` more bytes to be bump allocated.
2865    /// The bump allocator may reserve more space to avoid frequent reallocations.
2866    /// After calling `reserve_bytes`, <code>self.[stats](Self::stats)().[remaining](Stats::remaining)()</code> will be greater than or equal to
2867    /// `additional`. Does nothing if the capacity is already sufficient.
2868    ///
2869    /// # Errors
2870    /// Errors if the allocation fails.
2871    ///
2872    /// # Examples
2873    /// ```
2874    /// # use bump_scope::Bump;
2875    /// let bump: Bump = Bump::try_new()?;
2876    /// assert!(bump.stats().capacity() < 4096);
2877    ///
2878    /// bump.try_reserve_bytes(4096)?;
2879    /// assert!(bump.stats().capacity() >= 4096);
2880    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2881    /// ```
2882    #[inline(always)]
2883    pub fn try_reserve_bytes(&self, additional: usize) -> Result<(), AllocError> {
2884        self.generic_reserve_bytes(additional)
2885    }
2886
2887    #[inline(always)]
2888    pub(crate) fn generic_reserve_bytes<B: ErrorBehavior>(&self, additional: usize) -> Result<(), B> {
2889        let Ok(layout) = Layout::from_size_align(additional, 1) else {
2890            return Err(B::capacity_overflow());
2891        };
2892
2893        if let Some(mut chunk) = self.chunk.get().guaranteed_allocated() {
2894            let mut additional = additional;
2895
2896            loop {
2897                if let Some(rest) = additional.checked_sub(chunk.remaining()) {
2898                    additional = rest;
2899                } else {
2900                    return Ok(());
2901                }
2902
2903                if let Some(next) = chunk.next() {
2904                    chunk = next;
2905                } else {
2906                    break;
2907                }
2908            }
2909
2910            chunk.append_for(layout).map(drop)
2911        } else {
2912            let allocator = A::default_or_panic();
2913            let new_chunk = RawChunk::new_in(
2914                ChunkSize::from_capacity(layout).ok_or_else(B::capacity_overflow)?,
2915                None,
2916                allocator,
2917            )?;
2918            self.chunk.set(new_chunk.coerce_guaranteed_allocated());
2919            Ok(())
2920        }
2921    }
2922
2923    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
2924    ///
2925    /// 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.
2926    ///
2927    /// There is also [`alloc_try_with_mut`](Self::alloc_try_with_mut), optimized for a mutable reference.
2928    ///
2929    /// # Panics
2930    /// Panics if the allocation fails.
2931    ///
2932    /// # Examples
2933    #[cfg_attr(feature = "nightly-tests", doc = "```")]
2934    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
2935    /// # #![feature(offset_of_enum)]
2936    /// # use core::mem::offset_of;
2937    /// # use bump_scope::Bump;
2938    /// # let bump: Bump = Bump::new();
2939    /// let result = bump.alloc_try_with(|| -> Result<i32, i32> { Ok(123) });
2940    /// assert_eq!(result.unwrap(), 123);
2941    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
2942    /// ```
2943    #[cfg_attr(feature = "nightly-tests", doc = "```")]
2944    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
2945    /// # use bump_scope::Bump;
2946    /// # let bump: Bump = Bump::new();
2947    /// let result = bump.alloc_try_with(|| -> Result<i32, i32> { Err(123) });
2948    /// assert_eq!(result.unwrap_err(), 123);
2949    /// assert_eq!(bump.stats().allocated(), 0);
2950    /// ```
2951    #[inline(always)]
2952    #[cfg(feature = "panic-on-alloc")]
2953    #[expect(clippy::missing_errors_doc)]
2954    pub fn alloc_try_with<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<BumpBox<'a, T>, E> {
2955        panic_on_error(self.generic_alloc_try_with(f))
2956    }
2957
2958    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
2959    ///
2960    /// 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.
2961    ///
2962    /// There is also [`try_alloc_try_with_mut`](Self::try_alloc_try_with_mut), optimized for a mutable reference.
2963    ///
2964    /// # Errors
2965    /// Errors if the allocation fails.
2966    ///
2967    /// # Examples
2968    #[cfg_attr(feature = "nightly-tests", doc = "```")]
2969    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
2970    /// # #![feature(offset_of_enum)]
2971    /// # use core::mem::offset_of;
2972    /// # use bump_scope::Bump;
2973    /// # let bump: Bump = Bump::try_new()?;
2974    /// let result = bump.try_alloc_try_with(|| -> Result<i32, i32> { Ok(123) })?;
2975    /// assert_eq!(result.unwrap(), 123);
2976    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
2977    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2978    /// ```
2979    #[cfg_attr(feature = "nightly-tests", doc = "```")]
2980    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
2981    /// # use bump_scope::Bump;
2982    /// # let bump: Bump = Bump::try_new()?;
2983    /// let result = bump.try_alloc_try_with(|| -> Result<i32, i32> { Err(123) })?;
2984    /// assert_eq!(result.unwrap_err(), 123);
2985    /// assert_eq!(bump.stats().allocated(), 0);
2986    /// # Ok::<(), bump_scope::alloc::AllocError>(())
2987    /// ```
2988    #[inline(always)]
2989    pub fn try_alloc_try_with<T, E>(
2990        &self,
2991        f: impl FnOnce() -> Result<T, E>,
2992    ) -> Result<Result<BumpBox<'a, T>, E>, AllocError> {
2993        self.generic_alloc_try_with(f)
2994    }
2995
2996    #[inline(always)]
2997    pub(crate) fn generic_alloc_try_with<B: ErrorBehavior, T, E>(
2998        &self,
2999        f: impl FnOnce() -> Result<T, E>,
3000    ) -> Result<Result<BumpBox<'a, T>, E>, B> {
3001        if T::IS_ZST {
3002            return match f() {
3003                Ok(value) => Ok(Ok(BumpBox::zst(value))),
3004                Err(error) => Ok(Err(error)),
3005            };
3006        }
3007
3008        let checkpoint_before_alloc = self.checkpoint();
3009        let uninit = self.generic_alloc_uninit::<B, Result<T, E>>()?;
3010        let ptr = BumpBox::into_raw(uninit).cast::<Result<T, E>>();
3011
3012        // When bumping downwards the chunk's position is the same as `ptr`.
3013        // Using `ptr` is faster so we use that.
3014        let pos = if UP { self.chunk.get().pos() } else { ptr.cast() };
3015
3016        Ok(unsafe {
3017            non_null::write_with(ptr, f);
3018
3019            // If `f` made allocations on this bump allocator we can't shrink the allocation.
3020            let can_shrink = pos == self.chunk.get().pos();
3021
3022            match non_null::result(ptr) {
3023                Ok(value) => Ok({
3024                    if can_shrink {
3025                        let new_pos = if UP {
3026                            let pos = value.add(1).addr().get();
3027                            up_align_usize_unchecked(pos, MIN_ALIGN)
3028                        } else {
3029                            let pos = value.addr().get();
3030                            down_align_usize(pos, MIN_ALIGN)
3031                        };
3032
3033                        // The allocation of a non-ZST was successful, so our chunk must be allocated.
3034                        let chunk = self.chunk.get().guaranteed_allocated_unchecked();
3035                        chunk.set_pos_addr(new_pos);
3036                    }
3037
3038                    BumpBox::from_raw(value)
3039                }),
3040                Err(error) => Err({
3041                    let error = error.as_ptr().read();
3042
3043                    if can_shrink {
3044                        self.reset_to(checkpoint_before_alloc);
3045                    }
3046
3047                    error
3048                }),
3049            }
3050        })
3051    }
3052
3053    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
3054    ///
3055    /// 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.
3056    ///
3057    /// This is just like [`alloc_try_with`](Self::alloc_try_with), but optimized for a mutable reference.
3058    ///
3059    /// # Panics
3060    /// Panics if the allocation fails.
3061    ///
3062    /// # Examples
3063    #[cfg_attr(feature = "nightly-tests", doc = "```")]
3064    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
3065    /// # #![feature(offset_of_enum)]
3066    /// # use core::mem::offset_of;
3067    /// # use bump_scope::Bump;
3068    /// # let mut bump: Bump = Bump::new();
3069    /// let result = bump.alloc_try_with_mut(|| -> Result<i32, i32> { Ok(123) });
3070    /// assert_eq!(result.unwrap(), 123);
3071    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
3072    /// ```
3073    #[cfg_attr(feature = "nightly-tests", doc = "```")]
3074    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
3075    /// # use bump_scope::Bump;
3076    /// # let mut bump: Bump = Bump::new();
3077    /// let result = bump.alloc_try_with_mut(|| -> Result<i32, i32> { Err(123) });
3078    /// assert_eq!(result.unwrap_err(), 123);
3079    /// assert_eq!(bump.stats().allocated(), 0);
3080    /// ```
3081    #[inline(always)]
3082    #[cfg(feature = "panic-on-alloc")]
3083    #[expect(clippy::missing_errors_doc)]
3084    pub fn alloc_try_with_mut<T, E>(&mut self, f: impl FnOnce() -> Result<T, E>) -> Result<BumpBox<'a, T>, E> {
3085        panic_on_error(self.generic_alloc_try_with_mut(f))
3086    }
3087
3088    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
3089    ///
3090    /// 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.
3091    ///
3092    /// This is just like [`try_alloc_try_with`](Self::try_alloc_try_with), but optimized for a mutable reference.
3093    ///
3094    /// # Errors
3095    /// Errors if the allocation fails.
3096    ///
3097    /// # Examples
3098    #[cfg_attr(feature = "nightly-tests", doc = "```")]
3099    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
3100    /// # #![feature(offset_of_enum)]
3101    /// # use core::mem::offset_of;
3102    /// # use bump_scope::Bump;
3103    /// # let mut bump: Bump = Bump::try_new()?;
3104    /// let result = bump.try_alloc_try_with_mut(|| -> Result<i32, i32> { Ok(123) })?;
3105    /// assert_eq!(result.unwrap(), 123);
3106    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
3107    /// # Ok::<(), bump_scope::alloc::AllocError>(())
3108    /// ```
3109    #[cfg_attr(feature = "nightly-tests", doc = "```")]
3110    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
3111    /// # use bump_scope::Bump;
3112    /// # let mut bump: Bump = Bump::try_new()?;
3113    /// let result = bump.try_alloc_try_with_mut(|| -> Result<i32, i32> { Err(123) })?;
3114    /// assert_eq!(result.unwrap_err(), 123);
3115    /// assert_eq!(bump.stats().allocated(), 0);
3116    /// # Ok::<(), bump_scope::alloc::AllocError>(())
3117    /// ```
3118    #[inline(always)]
3119    pub fn try_alloc_try_with_mut<T, E>(
3120        &mut self,
3121        f: impl FnOnce() -> Result<T, E>,
3122    ) -> Result<Result<BumpBox<'a, T>, E>, AllocError> {
3123        self.generic_alloc_try_with_mut(f)
3124    }
3125
3126    #[inline(always)]
3127    pub(crate) fn generic_alloc_try_with_mut<B: ErrorBehavior, T, E>(
3128        &mut self,
3129        f: impl FnOnce() -> Result<T, E>,
3130    ) -> Result<Result<BumpBox<'a, T>, E>, B> {
3131        if T::IS_ZST {
3132            return match f() {
3133                Ok(value) => Ok(Ok(BumpBox::zst(value))),
3134                Err(error) => Ok(Err(error)),
3135            };
3136        }
3137
3138        let checkpoint = self.checkpoint();
3139        let ptr = self.generic_prepare_allocation::<B, Result<T, E>>()?;
3140
3141        Ok(unsafe {
3142            non_null::write_with(ptr, f);
3143
3144            // There is no need for `can_shrink` checks, because we have a mutable reference
3145            // so there's no way anyone else has allocated in `f`.
3146            match non_null::result(ptr) {
3147                Ok(value) => Ok({
3148                    let new_pos = if UP {
3149                        let pos = value.add(1).addr().get();
3150                        up_align_usize_unchecked(pos, MIN_ALIGN)
3151                    } else {
3152                        let pos = value.addr().get();
3153                        down_align_usize(pos, MIN_ALIGN)
3154                    };
3155
3156                    // The allocation of a non-ZST was successful, so our chunk must be allocated.
3157                    let chunk = self.chunk.get().guaranteed_allocated_unchecked();
3158                    chunk.set_pos_addr(new_pos);
3159
3160                    BumpBox::from_raw(value)
3161                }),
3162                Err(error) => Err({
3163                    let error = error.as_ptr().read();
3164                    self.reset_to(checkpoint);
3165                    error
3166                }),
3167            }
3168        })
3169    }
3170}