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