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}