Skip to main content

static_alloc/
bump.rs

1//! The bump allocator.
2//!
3//! Basics of usage and the connection between the structs is discussed in the documentation of the
4//! [`Bump`] itself.
5//!
6//! [`Bump`]: struct.Bump.html
7use core::alloc::{GlobalAlloc, Layout};
8use core::cell::UnsafeCell;
9use core::mem::{self, MaybeUninit};
10use core::ptr::{NonNull, null_mut};
11
12#[cfg(not(feature = "polyfill"))]
13use core::sync::atomic::{AtomicUsize, Ordering};
14
15#[cfg(feature = "polyfill")]
16use portable_atomic::{AtomicUsize, Ordering};
17
18use crate::leaked::LeakBox;
19use alloc_traits::{AllocTime, LocalAlloc, NonZeroLayout};
20
21/// Allocator drawing from an inner, statically sized memory resource.
22///
23/// The type parameter `T` is used only to annotate the required size and alignment of the region
24/// and has no futher use. Note that in particular there is no safe way to retrieve or unwrap an
25/// inner instance even if the `Bump` was not constructed as a shared global static. Nevertheless,
26/// the choice of type makes it easier to reason about potentially required extra space due to
27/// alignment padding.
28///
29/// This type is *always* `Sync` to allow creating `static` instances. This works only because
30/// there is no actual instance of `T` contained inside.
31///
32/// ## Usage as global allocator
33///
34/// You can use the stable rust attribute to use an instance of this type as the global allocator.
35///
36/// ```rust,no_run
37/// use static_alloc::Bump;
38///
39/// #[global_allocator]
40/// static A: Bump<[u8; 1 << 16]> = Bump::uninit();
41///
42/// fn main() { }
43/// ```
44///
45/// Take care, some runtime features of Rust will allocate some memory before or after your own
46/// code. In particular, it was found to be be tricky to predict the usage of the builtin test
47/// framework which seemingly allocates some structures per test.
48///
49/// ## Usage as a non-dropping local allocator
50///
51/// It is also possible to use a `Bump` as a stack local allocator or a specialized allocator. The
52/// interface offers some utilities for allocating values from references to shared or unshared
53/// instances directly. **Note**: this will never call the `Drop` implementation of the allocated
54/// type. In particular, it would almost surely not be safe to `Pin` the values, except if there is
55/// a guarantee for the `Bump` itself to not be deallocated either.
56///
57/// ```rust
58/// use static_alloc::Bump;
59///
60/// let local: Bump<[u64; 3]> = Bump::uninit();
61///
62/// let one = local.leak(0_u64).unwrap();
63/// let two = local.leak(1_u64).unwrap();
64/// let three = local.leak(2_u64).unwrap();
65///
66/// // Exhausted the space.
67/// assert!(local.leak(3_u64).is_err());
68/// ```
69///
70/// Mind that the supplied type parameter influenced *both* size and alignment and a `[u8; 24]`
71/// does not guarantee being able to allocation three `u64` even though most targets have a minimum
72/// alignment requirement of 16 and it works fine on those.
73///
74/// ```rust
75/// # use static_alloc::Bump;
76/// // Just enough space for `u128` but no alignment requirement.
77/// let local: Bump<[u8; 16]> = Bump::uninit();
78///
79/// // May or may not return an err.
80/// let _ = local.leak(0_u128);
81/// ```
82///
83/// Instead use the type parameter to `Bump` as a hint for the best alignment.
84///
85/// ```rust
86/// # use static_alloc::Bump;
87/// // Enough space and align for `u128`.
88/// let local: Bump<[u128; 1]> = Bump::uninit();
89///
90/// assert!(local.leak(0_u128).is_ok());
91/// ```
92///
93/// ## Usage as a (local) bag of bits
94///
95/// It is of course entirely possible to use a local instance instead of a single global allocator.
96/// For example you could utilize the pointer interface directly to build a `#[no_std]` dynamic
97/// data structure in an environment without `extern lib alloc`. This feature was the original
98/// motivation behind the crate but no such data structures are provided here so a quick sketch of
99/// the idea must do:
100///
101/// ```
102/// use core::alloc;
103/// use static_alloc::Bump;
104///
105/// #[repr(align(4096))]
106/// struct PageTable {
107///     // some non-trivial type.
108/// #   _private: [u8; 4096],
109/// }
110///
111/// impl PageTable {
112///     /// Avoid stack allocation of the full struct.
113///     pub unsafe fn new(into: *mut u8) -> &'static mut Self {
114///         // ...
115/// #       &mut *(into as *mut Self)
116///     }
117/// }
118///
119/// // Allocator for pages for page tables. Provides 64 pages. When the
120/// // program/kernel is provided as an ELF the bootloader reserves
121/// // memory for us as part of the loading process that we can use
122/// // purely for page tables. Replaces asm `paging: .BYTE <size>;`
123/// static Paging: Bump<[u8; 1 << 18]> = Bump::uninit();
124///
125/// fn main() {
126///     let layout = alloc::Layout::new::<PageTable>();
127///     let memory = Paging.alloc(layout).unwrap();
128///     let table = unsafe {
129///         PageTable::new(memory.as_ptr())
130///     };
131/// }
132/// ```
133///
134/// A similar structure would of course work to allocate some non-`'static' objects from a
135/// temporary `Bump`.
136///
137/// ## More insights
138///
139/// The ordering used is currently `SeqCst`. This enforces a single global sequence of observed
140/// effects on the slab level. The author is fully aware that this is not strictly necessary. In
141/// fact, even `AcqRel` may not be required as the monotonic bump allocator does not synchronize
142/// other memory itself. If you bring forward a PR with a formalized reasoning for relaxing the
143/// requirements to `Relaxed` (llvm `Monotonic`) it will be greatly appreciated (even more if you
144/// demonstrate performance gains).
145///
146/// WIP: slices.
147#[repr(C)]
148pub struct Bump<T> {
149    /// While in shared state, an monotonic atomic counter of consumed bytes.
150    ///
151    /// While shared it is only mutated in `bump` which guarantees its invariants. In the mutable
152    /// reference state it is modified arbitrarily.
153    header: Header,
154
155    /// Outer unsafe cell due to thread safety.
156    /// Inner MaybeUninit because we padding may destroy initialization invariant
157    /// on the bytes themselves, and hence drop etc must not assumed inited.
158    storage: UnsafeCell<MaybeUninit<T>>,
159}
160
161/// An unsized bump allocator arena.
162///
163/// This does not enforce any particular alignment on its storage. You can, in general, expect that
164/// it is at least 4-byte aligned but should not rely on it for soundness purposes.
165#[repr(C)]
166pub struct BumpSlice {
167    /// While in shared state, an monotonic atomic counter of consumed bytes.
168    ///
169    /// While shared it is only mutated in `bump` which guarantees its invariants. In the mutable
170    /// reference state it is modified arbitrarily.
171    header: Header,
172
173    /// See [`Bump::storage`], same function but with a concrete type.
174    storage: UnsafeCell<[MaybeUninit<u8>]>,
175}
176
177/// A view of a bump allocator over an unsized arena.
178///
179/// The primary way of constructing this is a by [`Bump`] with some chosen layout descriptor type.
180/// It maintains the invariant of a tracking header being an accurate ledger for the use of its
181/// associated memory region. This implies you must not be allowed to combine any header and data.
182/// This strong association is protected by an area such as [`Bump`].
183///
184/// Note: You might think that we can
185#[derive(Clone, Copy)]
186pub(crate) struct BumpView<'lt> {
187    header: &'lt Header,
188    storage: &'lt UnsafeCell<[MaybeUninit<u8>]>,
189}
190
191/// NOTE: see the problem of freely dereferencing a `Bump<T>` into `BumpSlice` where the offset of
192/// `storage` must not be affected. This is caused by the align of `T` exceeding that of the header.
193/// If instead we included such information into the header we could fully support this
194/// dereferencing again, at the cost of a few bits. There is no need to actually read those bits
195/// when we're using it in a `Bump` as we only need to reconstruct the right `storage` slice when
196/// used as a `BumpSlice`. The extra struct padding will only appear as more MaybeUninit data in the
197/// unsized type.
198#[repr(C)]
199struct Header {
200    consumed: AtomicUsize,
201}
202
203/// A value could not be moved into a slab allocation.
204///
205/// The error contains the value for which the allocation failed. Storing the value in the error
206/// keeps it alive in all cases. This prevents the `Drop` implementation from running and preserves
207/// resources which may otherwise not be trivial to restore.
208#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
209pub struct LeakError<T> {
210    val: T,
211    failure: Failure,
212}
213
214/// Specifies an amount of consumed space of a slab.
215///
216/// Each allocation of the `Bump` increases the current level as they must not be empty. By
217/// ensuring that an allocation is performed at a specific level it is thus possible to check that
218/// multiple allocations happened in succession without other intermediate allocations. This
219/// ability in turns makes it possible to group allocations together, for example to initialize a
220/// `#[repr(C)]` struct member-by-member or to extend a slice.
221///
222/// ## Usage
223///
224/// The main use is successively allocating a slice without requiring all data to be present at
225/// once. Other similar interface often require an internal locking mechanism but `Level` leaves
226/// the choice to the user. This is not yet encapsulate in a safe API yet `Level` makes it easy to
227/// reason about.
228///
229/// See [`MemBump::get_unchecked`](`crate::bump::BumpSlice`) for redeeming a value.
230///
231/// ## Unsound usage.
232///
233/// FIXME: the below is UB because we don't gain provenance over the complete array, only each
234/// individual element. Instead, we must derive a new pointer from the allocator!
235///
236/// ```
237/// # use core::slice;
238/// # use static_alloc::bump::{Level, Bump};
239/// static BUMP: Bump<[u64; 4]> = Bump::uninit();
240///
241/// /// Gathers as much data as possible.
242/// ///
243/// /// An arbitrary amount of data, can't stack allocate!
244/// fn gather_data(mut iter: impl Iterator<Item=u64>) -> &'static mut [u64] {
245///     let first = match iter.next() {
246///         Some(item) => item,
247///         None => return &mut [],
248///     };
249///
250///     let mut level: Level = BUMP.level();
251///     let mut start: Level = BUMP.level();
252///     let mut count;
253///
254///     match BUMP.leak_at(first, level) {
255///         Ok((_first, first_level)) => {
256///             // Note we must throw away the first pointer. Its provenance does not
257///             // cover the other fields. Only its level can be used.
258///             level = first_level;
259///             count = 1;
260///         },
261///         _ => return &mut [],
262///     }
263///
264///     let _ = iter.try_for_each(|value: u64| {
265///         match BUMP.leak_at(value, level) {
266///             Err(err) => return Err(err),
267///             Ok((_, new_level)) => level = new_level,
268///         };
269///         count += 1;
270///         Ok(())
271///     });
272///
273///     unsafe {
274///         // Safety: we have an allocation here
275///         let begin = BUMP.get_unchecked(start);
276///         // SAFETY: all `count` allocations are contiguous, begin is well aligned and no
277///         // reference is currently pointing at any of the values. The lifetime is `'static` as
278///         // the BUMP itself is static.
279///         slice::from_raw_parts_mut(begin.ptr.as_ptr(), count)
280///     }
281/// }
282///
283/// fn main() {
284///     // There is no other thread running, so this succeeds.
285///     let slice = gather_data(0..=3);
286///     assert_eq!(slice, [0, 1, 2, 3]);
287/// }
288/// ```
289#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
290pub struct Level(pub(crate) usize);
291
292impl Level {
293    /// Get the byte offset with respect to the arena [`data_ptr`](`Bump::data_ptr`).
294    pub fn byte_offset(&self) -> usize {
295        self.0
296    }
297}
298
299/// A successful allocation and current [`Level`].
300///
301/// [`Level`]: struct.Level.html
302///
303/// ## Design notes
304///
305/// The `ptr` field is, when returned by an allocator, always a valid pointer. However, we can not
306/// express this as a mutable reference to `MaybeUninit` for unsized types. Instead, a pointer is
307/// needed to provide address, provenance, and pointer metadata. The cost of this is that we discard
308/// the validity information which has to be unsafely re-applied by the user (of course, verifying
309/// that the point actually is valid since this type is fully public).
310#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
311pub struct Allocation<'a, T: ?Sized = u8> {
312    /// Pointer to the uninitialized region with specified layout.
313    pub ptr: NonNull<T>,
314
315    /// The lifetime of the allocation.
316    pub lifetime: AllocTime<'a>,
317
318    /// The observed amount of consumed bytes after the allocation.
319    ///
320    /// For `Bump` this is precise, i.e. the offset of the `ptr` in the arena data is the level's
321    /// byte offset minus the layout size.
322    pub level: Level,
323}
324
325impl<T> Allocation<'_, T> {
326    /// Get the `Level` at which the allocation starts.
327    ///
328    /// This can be used as the level of [`Bump::get_unchecked`] with the arena it as allocated
329    /// from. There is an equivalent method for some unsized types.
330    ///
331    /// # Usage
332    ///
333    /// ```
334    /// use static_alloc::Bump;
335    ///
336    /// let arena = Bump::<[u32; 4]>::uninit();
337    /// let alloc = arena.get::<u32>().unwrap();
338    ///
339    /// assert_eq!(alloc.level.byte_offset(), 4);
340    /// assert_eq!(alloc.level_start().byte_offset(), 0);
341    /// ```
342    pub fn level_start(&self) -> Level {
343        Level(self.level.byte_offset() - mem::size_of::<T>())
344    }
345}
346
347impl<T> Allocation<'_, [T]> {
348    /// Get the `Level` at which the allocation starts.
349    ///
350    /// This can be used as the level of [`Bump::get_unchecked`] with the arena it as allocated
351    /// from. There is an equivalent method for some unsized types.
352    ///
353    /// See the sized [`Allocation::level_start`].
354    pub fn level_start(&self) -> Level {
355        Level(self.level.byte_offset() - mem::size_of::<T>() * self.ptr.len())
356    }
357}
358
359/// Reason for a failed allocation at an exact [`Level`].
360///
361/// [`Level`]: struct.Level.html
362#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
363pub enum Failure {
364    /// No space left for that allocation.
365    Exhausted,
366
367    /// The allocation would not have used the expected base location.
368    ///
369    /// Reports the location that was observed. When only levels from the same slab are used (which
370    /// should normally be the case) then the observed level is monotonically increasing.
371    Mismatch {
372        /// The observed level that was different from the requested one.
373        observed: Level,
374    },
375}
376
377impl<T> Bump<T> {
378    /// Make a new allocatable slab of certain byte size and alignment.
379    ///
380    /// The storage will contain uninitialized bytes.
381    pub const fn uninit() -> Self {
382        Bump {
383            header: Header::empty(),
384            storage: UnsafeCell::new(MaybeUninit::uninit()),
385        }
386    }
387
388    /// Make a new allocatable slab of certain byte size and alignment.
389    ///
390    /// The storage will contain zeroed bytes. This is not *yet* available
391    /// as a `const fn` which currently limits its potential usefulness
392    /// but there is no good reason not to provide it regardless.
393    pub fn zeroed() -> Self {
394        Bump {
395            header: Header::empty(),
396            storage: UnsafeCell::new(MaybeUninit::zeroed()),
397        }
398    }
399
400    /// Make a new allocatable slab provided with some bytes it can hand out.
401    ///
402    /// Note that `storage` will never be dropped and there is no way to get it back.
403    pub const fn new(storage: T) -> Self {
404        Bump {
405            header: Header::empty(),
406            storage: UnsafeCell::new(MaybeUninit::new(storage)),
407        }
408    }
409
410    /// Convert this into a type-erased byte-slice bump allocator.
411    ///
412    /// This returns `None` if the layout of `T` causes the layout of `self` to not be compatible
413    /// with the layout of [`BumpSlice`]. The criteria is that `T` must have an alignment not greater
414    /// than that of `usize` (which is used internally for accounting the used portion).
415    ///
416    /// For instance, this is guaranteed to work:
417    ///
418    /// ```
419    /// use static_alloc::Bump;
420    ///
421    /// let byte_array: Bump<[u8; 128]> = Bump::uninit();
422    /// assert!(byte_array.as_bump_slice().is_some());
423    /// let usize_array: Bump<[usize; 128]> = Bump::uninit();
424    /// assert!(usize_array.as_bump_slice().is_some());
425    /// ```
426    ///
427    /// On the other hand, this is very unlikely to work on any platform:
428    ///
429    /// ```
430    /// # if core::mem::size_of::<usize>() < 32 {
431    /// use static_alloc::Bump;
432    ///
433    /// #[repr(C, align(32))]
434    /// struct WhyAlignSoHigh([u8; 128]);
435    ///
436    /// let oof: Bump<WhyAlignSoHigh> = Bump::uninit();
437    /// assert!(oof.as_bump_slice().is_none());
438    /// # }
439    /// ```
440    pub const fn as_bump_slice(&self) -> Option<&BumpSlice> {
441        // Safety:
442        if mem::offset_of!(Self, storage) != mem::size_of::<Header>() {
443            return None;
444        }
445
446        let data_len = mem::size_of::<T>();
447        // Construct a point with the meta data of a slice to `data`, but pointing to the whole
448        // struct instead. This meta data is later copied to the meta data of `bump` when cast.
449        let ptr = (self as *const Self).cast::<MaybeUninit<u8>>();
450        let mem: *const [MaybeUninit<u8>] = core::ptr::slice_from_raw_parts(ptr, data_len);
451
452        // Safety: The layout of this type is compatible with ours. Both are `repr(C)`, so we can go
453        // field-by-field and the total layout.
454        //
455        // - Firstly, they share a `Header` field.
456        // - Secondly, `data` is located immediately behind `Header`. In `self` we verify this
457        //   above, in `BumpSlice` that follows directly from `u8` being 1-aligned.
458        // - The alignment requirement of `MemBump`, exactly that of `Header`, is fulfilled as that
459        //   is also a field of `Self`.
460        // - The size of both values is compatible. We construct the metadata such that the return
461        //   value covers exactly the length of the `storage` field. What follows is padding to
462        //   cover the alignment requirement. The `Self` type has the same alignment and same offset
463        //   past-the-field and hence will receive the same padding.
464        Some(unsafe { &*(mem as *const BumpSlice) })
465    }
466
467    /// Mutable variant of [`Self::as_bump_slice`].
468    pub const fn as_mut_bump_slice(&mut self) -> Option<&mut BumpSlice> {
469        // Safety:
470        if mem::offset_of!(Self, storage) != mem::size_of::<Header>() {
471            return None;
472        }
473
474        let data_len = mem::size_of::<T>();
475        // Construct a point with the meta data of a slice to `data`, but pointing to the whole
476        // struct instead. This meta data is later copied to the meta data of `bump` when cast.
477        let ptr = (self as *mut Self).cast::<MaybeUninit<u8>>();
478        let mem: *mut [MaybeUninit<u8>] = core::ptr::slice_from_raw_parts_mut(ptr, data_len);
479
480        // Safety: The layout of this type is compatible with ours. Both are `repr(C)`, so we can go
481        // field-by-field and the total layout.
482        //
483        // - Firstly, they share a `Header` field.
484        // - Secondly, `data` is located immediately behind `Header`. In `self` we verify this
485        //   above, in `MemBump` that follows directly from `u8` being 1-aligned.
486        // - The alignment requirement of `MemBump`, exactly that of `Header`, is fulfilled as that
487        //   is also a field of `Self`.
488        // - The size of both values is compatible. We construct the metadata such that the return
489        //   value covers exactly the length of the `storage` field. What follows is padding to
490        //   cover the alignment requirement. The `Self` type has the same alignment and same offset
491        //   past-the-field and hence will receive the same padding.
492        Some(unsafe { &mut *(mem as *mut BumpSlice) })
493    }
494
495    /// Construct a bump allocator into an uninitialized memory location.
496    ///
497    /// This fills in only a constant sized header. The rest of the allocation is left-as, i.e. if
498    /// remains initialized exactly in those spots the caller may have initialized with external
499    /// means.
500    ///
501    /// Note that this method is `const` (though this is not particularly useful yet as of `0.3.0`).
502    ///
503    /// # Usage
504    ///
505    /// This method allows `Bump` to be used together with interfaces that require an outer
506    /// `MaybeUninit` for their safety proofs, e.g. [`Box::new_uninit_slice`].
507    ///
508    /// ```
509    /// # use static_alloc::bump::Bump;
510    /// type Allocator = Bump<[u32; 128]>;
511    ///
512    /// # let num_components = 4;
513    /// // 4 independent allocators, e.g. for four components of your software.
514    /// // Still guaranteed to live in consecutive memory.
515    /// let mut allocators = Box::<[Allocator]>::new_uninit_slice(num_components);
516    ///
517    /// // The index here might be a runtime address.
518    /// // Now this arena can be used without initializing the others already.
519    /// let c0 = Bump::from_maybe_uninit(&mut allocators[0]);
520    /// // Etc. Use this temporary stack allocator.
521    /// let _ = c0.leak_box(0xdead_beefusize);
522    /// ```
523    pub const fn from_maybe_uninit(data: &mut MaybeUninit<Self>) -> &'_ mut Self {
524        // Safety: dereferencing a pointer into a `&mut MaybeUninit`.
525        let header = unsafe { &raw mut (*data.as_mut_ptr()).header };
526        // Safety: pointer points into a `MaybeUninit` which we have derived a mutable provenance
527        // pointer into.
528        unsafe { core::ptr::write(header, Header::empty()) };
529        // Safety: only the header field requires initialization. The storage is a no-op.
530        unsafe { data.assume_init_mut() }
531    }
532
533    /// Construct a bump allocator into an existing dynamically sized arena of memory.
534    ///
535    /// Note that this method also exists for a dynamically sized
536    /// [`BumpSlice`][`BumpSlice::from_memory`] which can make use of almost arbitrarily sized
537    /// blocks of data. In comparison, this method requires that at least `size_of::<Self>` data at
538    /// an aligned location in the slice is available.
539    ///
540    /// Returns `None` if there are not enough bytes beyond the first aligned offset to hold a value
541    /// of `Self` type.
542    ///
543    /// # Usage
544    ///
545    /// This way you may re-use storage from some arbitrary existing span of memory, provided it has
546    /// at least enough room to hold an aligned header.
547    ///
548    /// ```
549    /// use core::mem::MaybeUninit;
550    /// use static_alloc::bump::Bump;
551    /// # fn example() -> Option<()> {
552    ///
553    /// let mut buffer = MaybeUninit::<[u8; 256]>::uninit();
554    /// let bump = Bump::<[u8; 200]>::from_memory(buffer.as_mut())?;
555    ///
556    /// // Slightly less than 256 free bytes of memory to use.
557    /// // Exact number is unstable and depends on the align of `buffer`.
558    /// let allocated_slice = bump.get_slice::<u32>(50)?;
559    ///
560    /// # Some(()) }
561    /// ```
562    pub fn from_memory(data: &mut [MaybeUninit<u8>]) -> Option<&'_ mut Self> {
563        // Safety: `MaybeUninit<Self>` is always valid.
564        let (_, usable, _) = unsafe { data.align_to_mut::<MaybeUninit<Self>>() };
565        usable.first_mut().map(Self::from_maybe_uninit)
566    }
567
568    /// Reset the bump allocator.
569    ///
570    /// Requires a mutable reference, as no allocations can be active when doing it. This behaves
571    /// as if a fresh instance was assigned but it does not overwrite the bytes in the backing
572    /// storage. (You can unsafely rely on this).
573    ///
574    /// ## Usage
575    ///
576    /// ```
577    /// # use static_alloc::Bump;
578    /// let mut stack_buf = Bump::<usize>::uninit();
579    ///
580    /// let bytes = stack_buf.leak(0usize.to_be_bytes()).unwrap();
581    /// // Now the bump allocator is full.
582    /// assert!(stack_buf.leak(0u8).is_err());
583    ///
584    /// // We can reuse if we are okay with forgetting the previous value.
585    /// stack_buf.reset();
586    /// let val = stack_buf.leak(0usize).unwrap();
587    /// ```
588    ///
589    /// Trying to use the previous value does not work, as the stack is still borrowed. Note that
590    /// any user unsafely tracking the lifetime must also ensure this through proper lifetimes that
591    /// guarantee that borrows are alive for appropriate times.
592    ///
593    /// ```compile_fail
594    /// // error[E0502]: cannot borrow `stack_buf` as mutable because it is also borrowed as immutable
595    /// # use static_alloc::Bump;
596    /// let mut stack_buf = Bump::<usize>::uninit();
597    ///
598    /// let bytes = stack_buf.leak(0usize).unwrap();
599    /// //          --------- immutably borrow occurs here
600    /// stack_buf.reset();
601    /// // ^^^^^^^ mutable borrow occurs here.
602    /// let other = stack_buf.leak(0usize).unwrap();
603    ///
604    /// *bytes += *other;
605    /// // ------------- immutable borrow later used here
606    /// ```
607    pub fn reset(&mut self) {
608        self.header = Header::empty();
609    }
610
611    pub(crate) fn as_view(&self) -> BumpView<'_> {
612        BumpView {
613            header: &self.header,
614            storage: {
615                let base = self.storage.get();
616                let len = mem::size_of::<T>();
617                let data = core::ptr::slice_from_raw_parts(base as *const _, len);
618                // Safety: covers exactly the memory of `storage`, which is a `MaybeUninit`.
619                unsafe { &*(data as *const UnsafeCell<[_]>) }
620            },
621        }
622    }
623
624    /// Returns capacity of this allocator.
625    ///
626    /// This is how many *bytes* can be allocated within this allocator in total, with no
627    /// information about the currently consumed count.
628    pub const fn capacity(&self) -> usize {
629        mem::size_of::<T>()
630    }
631
632    /// Get a raw pointer to the data.
633    ///
634    /// Note that *any* use of the pointer must be done with extreme care as it may invalidate
635    /// existing references into the allocated region. Furthermore, bytes may not be initialized.
636    /// The length of the valid region is [`BumpSlice::capacity`].
637    ///
638    /// Prefer [`Self::get_unchecked`] for reconstructing a prior allocation.
639    pub fn data_ptr(&self) -> NonNull<u8> {
640        NonNull::from(&self.storage).cast()
641    }
642
643    /// Allocate a region of memory.
644    ///
645    /// This is a safe alternative to [GlobalAlloc::alloc](#impl-GlobalAlloc).
646    ///
647    /// # Panics
648    /// This function will panic if the requested layout has a size of `0`. For the use in a
649    /// `GlobalAlloc` this is explicitely forbidden to request and would allow any behaviour but we
650    /// instead strictly check it.
651    pub fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
652        self.as_view().alloc(layout)
653    }
654
655    /// Try to allocate some layout with a precise base location.
656    ///
657    /// The base location is the currently consumed byte count, without correction for the
658    /// alignment of the allocation. This will succeed if it can be allocate exactly at the
659    /// expected location.
660    ///
661    /// # Panics
662    /// This function may panic if the provided `level` is from a different slab.
663    pub fn alloc_at(&self, layout: Layout, level: Level) -> Result<Allocation<'_>, Failure> {
664        self.as_view().alloc_at(layout, level)
665    }
666
667    /// Get an allocation with detailed layout.
668    ///
669    /// Provides an [`Uninit`] wrapping several aspects of initialization in a safe interface,
670    /// bound by the lifetime of the reference to the allocator.
671    ///
672    /// [`Uninit`]: ../uninit/struct.Uninit.html
673    pub fn get_layout(&self, layout: Layout) -> Option<Allocation<'_>> {
674        self.as_view().get_layout(layout)
675    }
676
677    /// Get an allocation with detailed layout at a specific level.
678    ///
679    /// Provides an [`Uninit`] wrapping several aspects of initialization in a safe interface,
680    /// bound by the lifetime of the reference to the allocator.
681    ///
682    /// Since the underlying allocation is the same, it would be `unsafe` but justified to fuse
683    /// this allocation with the preceding or succeeding one.
684    ///
685    /// [`Uninit`]: ../uninit/struct.Uninit.html
686    pub fn get_layout_at(&self, layout: Layout, at: Level) -> Result<Allocation<'_>, Failure> {
687        self.as_view().get_layout_at(layout, at)
688    }
689
690    /// Get an allocation for a specific type.
691    ///
692    /// It is not yet initialized but provides a safe interface for that initialization.
693    ///
694    /// ## Usage
695    ///
696    /// ```
697    /// # use static_alloc::Bump;
698    /// use core::cell::{Ref, RefCell};
699    ///
700    /// let slab: Bump<[Ref<'static, usize>; 1]> = Bump::uninit();
701    /// let data = RefCell::new(0xff);
702    ///
703    /// // We can place a `Ref` here but we did not yet.
704    /// let alloc = slab.get::<Ref<usize>>().unwrap();
705    /// let cell_ref = unsafe {
706    ///     alloc.leak(data.borrow())
707    /// };
708    ///
709    /// assert_eq!(**cell_ref, 0xff);
710    /// ```
711    pub fn get<V>(&self) -> Option<Allocation<'_, V>> {
712        self.as_view().get()
713    }
714
715    /// Get an allocation for a specific type at a specific level.
716    ///
717    /// See [`get`](`Self::get`) for usage.
718    pub fn get_at<V>(&self, level: Level) -> Result<Allocation<'_, V>, Failure> {
719        self.as_view().get_at(level)
720    }
721
722    /// Get an allocation for a slice of a type.
723    ///
724    /// Returns `None` if the allocation fails (see [`Self::get`]) or if the slice layout can not be
725    /// computed due to an overflow with this size.
726    ///
727    /// # Examples
728    ///
729    /// ```
730    /// # use static_alloc::bump::Bump;
731    ///
732    /// let slab: Bump<[usize; 6]> = Bump::uninit();
733    ///
734    /// let first = slab.get_slice::<usize>(4).unwrap();
735    /// let second = slab.get_slice::<usize>(2).unwrap();
736    /// assert!(slab.get_slice::<usize>(1).is_none());
737    ///
738    /// assert_eq!(first.ptr.len(), 4);
739    /// assert_eq!(second.ptr.len(), 2);
740    /// ```
741    ///
742    /// ```
743    /// # use static_alloc::bump::Bump;
744    ///
745    /// let slab: Bump<[usize; 1]> = Bump::uninit();
746    ///
747    /// let lots_of_empty = slab.get_slice::<()>(usize::MAX).unwrap();
748    /// assert_eq!(lots_of_empty.ptr.len(), usize::MAX);
749    /// ```
750    ///
751    /// ```
752    /// # use static_alloc::bump::Bump;
753    ///
754    /// let slab: Bump<[usize; 1]> = Bump::uninit();
755    ///
756    /// let _exhaust = slab.get_slice::<usize>(1).unwrap();
757    /// assert!(slab.get_slice::<usize>(1).is_none());
758    /// let empty_slice = slab.get_slice::<usize>(0).unwrap();
759    /// ```
760    pub fn get_slice<V>(&self, len: usize) -> Option<Allocation<'_, [V]>> {
761        self.as_view().get_slice(len)
762    }
763
764    /// Move a value into an owned allocation.
765    ///
766    /// For safely initializing a value _after_ a successful allocation, see [`LeakBox::write`].
767    ///
768    /// [`LeakBox::write`]: ../leaked/struct.LeakBox.html#method.write
769    ///
770    /// ## Usage
771    ///
772    /// This can be used to push the value into a caller provided stack buffer where it lives
773    /// longer than the current stack frame. For example, you might create a linked list with a
774    /// dynamic number of values living in the frame below while still being dropped properly. This
775    /// is impossible to do with a return value.
776    ///
777    /// ```
778    /// # use static_alloc::Bump;
779    /// # use static_alloc::leaked::LeakBox;
780    /// fn rand() -> usize { 4 }
781    ///
782    /// enum Chain<'buf, T> {
783    ///    Tail,
784    ///    Link(T, LeakBox<'buf, Self>),
785    /// }
786    ///
787    /// fn make_chain<Buf, T>(buf: &Bump<Buf>, mut new_node: impl FnMut() -> T)
788    ///     -> Option<Chain<'_, T>>
789    /// {
790    ///     let count = rand();
791    ///     let mut chain = Chain::Tail;
792    ///     for _ in 0..count {
793    ///         let node = new_node();
794    ///         chain = Chain::Link(node, buf.leak_box(chain)?);
795    ///     }
796    ///     Some(chain)
797    /// }
798    ///
799    /// struct Node (usize);
800    /// impl Drop for Node {
801    ///     fn drop(&mut self) {
802    ///         println!("Dropped {}", self.0);
803    ///     }
804    /// }
805    /// let mut counter = 0..;
806    /// let new_node = || Node(counter.next().unwrap());
807    ///
808    /// let buffer: Bump<[u8; 128]> = Bump::uninit();
809    /// let head = make_chain(&buffer, new_node).unwrap();
810    ///
811    /// // Prints the message in reverse order.
812    /// // Dropped 3
813    /// // Dropped 2
814    /// // Dropped 1
815    /// // Dropped 0
816    /// drop(head);
817    /// ```
818    pub fn leak_box<V>(&self, val: V) -> Option<LeakBox<'_, V>> {
819        self.as_view().leak_box(val)
820    }
821
822    /// Move a value into an owned allocation.
823    ///
824    /// See [`leak_box`] for usage.
825    ///
826    /// [`leak_box`]: #method.leak_box
827    pub fn leak_box_at<V>(&self, val: V, level: Level) -> Result<LeakBox<'_, V>, Failure> {
828        self.as_view().leak_box_at(val, level)
829    }
830
831    /// Observe the current level.
832    ///
833    /// Keep in mind that concurrent usage of the same slab may modify the level before you are
834    /// able to use it in `alloc_at`. Calling this method provides also no other guarantees on
835    /// synchronization of memory accesses, only that the values observed by the caller are a
836    /// monotonically increasing seequence while a shared reference exists.
837    pub fn level(&self) -> Level {
838        self.as_view().level()
839    }
840
841    /// Get a pointer to an existing allocation at a specific level.
842    ///
843    /// The resulting pointer may be used to access an arbitrary allocation starting at the pointer
844    /// (i.e. including additional allocations immediately afterwards) but the caller is
845    /// responsible for ensuring that these accesses do not overlap other accesses. There must be
846    /// no more life [`LeakBox`] to any allocation being accessed this way.
847    ///
848    /// # Safety
849    ///
850    /// - The level must refer to an existing allocation, i.e. it must previously have been
851    ///   returned in [`Allocation::level_start`].
852    /// - As a corollary, particular it must be in-bounds of the allocator's memory.
853    /// - Another consequence, the result pointer must be aligned for the requested type.
854    pub unsafe fn get_unchecked<V>(&self, level: Level) -> Allocation<'_, V> {
855        // Safety: forwarding requirements.
856        unsafe { self.as_view().get_unchecked(level) }
857    }
858
859    /// Allocate a value for the lifetime of the allocator.
860    ///
861    /// The value is leaked in the sense that
862    ///
863    /// 1. the drop implementation of the allocated value is never called;
864    /// 2. reusing the memory for another allocation in the same `Bump` requires manual unsafe code
865    ///    to handle dropping and reinitialization.
866    ///
867    /// However, it does not mean that the underlying memory used for the allocated value is never
868    /// reclaimed. If the `Bump` itself is a stack value then it will get reclaimed together with
869    /// it.
870    ///
871    /// ## Safety notice
872    ///
873    /// It is important to understand that it is undefined behaviour to reuse the allocation for
874    /// the *whole lifetime* of the returned reference. That is, dropping the allocation in-place
875    /// while the reference is still within its lifetime comes with the exact same unsafety caveats
876    /// as [`ManuallyDrop::drop`](`core::mem::ManuallyDrop::drop`).
877    ///
878    /// ```
879    /// # use static_alloc::Bump;
880    /// #[derive(Debug, Default)]
881    /// struct FooBar {
882    ///     // ...
883    /// # _private: [u8; 1],
884    /// }
885    ///
886    /// let local: Bump<[FooBar; 3]> = Bump::uninit();
887    /// let one = local.leak(FooBar::default()).unwrap();
888    ///
889    /// // Dangerous but justifiable.
890    /// let one = unsafe {
891    ///     // Ensures there is no current mutable borrow.
892    ///     core::ptr::drop_in_place(&mut *one);
893    /// };
894    /// ```
895    ///
896    /// ## Usage
897    ///
898    /// ```
899    /// use static_alloc::Bump;
900    ///
901    /// let local: Bump<[u64; 3]> = Bump::uninit();
902    ///
903    /// let one = local.leak(0_u64).unwrap();
904    /// assert_eq!(*one, 0);
905    /// *one = 42;
906    /// ```
907    ///
908    /// ## Limitations
909    ///
910    /// Only sized values can be allocated in this manner for now, unsized values are blocked on
911    /// stabilization of [`ptr::slice_from_raw_parts`]. We can not otherwise get a fat pointer to
912    /// the allocated region.
913    ///
914    /// [`ptr::slice_from_raw_parts`]: https://github.com/rust-lang/rust/issues/36925
915    ///
916    /// TODO: will be deprecated sooner or later in favor of a method that does not move the
917    /// resource on failure.
918    // #[deprecated = "Use leak_box and initialize it with the value. This does not move the value in the failure case."]
919    #[expect(clippy::mut_from_ref)] // This is an allocator.
920    pub fn leak<V>(&self, val: V) -> Result<&mut V, LeakError<V>> {
921        match self.get::<V>() {
922            // SAFETY: Just allocated this for a `V`.
923            Some(alloc) => Ok(unsafe { alloc.leak(val) }),
924            None => Err(LeakError::new(val, Failure::Exhausted)),
925        }
926    }
927
928    /// Allocate a value with a precise location.
929    ///
930    /// See [`leak`] for basics on allocation of values.
931    ///
932    /// The level is an identifer for a base location (more at [`level`]). This will succeed if it
933    /// can be allocate exactly at the expected location.
934    ///
935    /// This method will return the new level of the slab allocator. A next allocation at the
936    /// returned level will be placed next to this allocation, only separated by necessary padding
937    /// from alignment. In particular, this is the same strategy as applied for the placement of
938    /// `#[repr(C)]` struct members. (Except for the final padding at the last member to the full
939    /// struct alignment.)
940    ///
941    /// ## Usage
942    ///
943    /// ```
944    /// use static_alloc::Bump;
945    ///
946    /// let local: Bump<[u64; 3]> = Bump::uninit();
947    ///
948    /// let base = local.level();
949    /// let (one, level) = local.leak_at(1_u64, base).unwrap();
950    /// // Will panic when an allocation happens in between.
951    /// let (two, _) = local.leak_at(2_u64, level).unwrap();
952    ///
953    /// assert_eq!((one as *const u64).wrapping_offset(1), two);
954    /// ```
955    ///
956    /// [`leak`]: #method.leak
957    /// [`level`]: #method.level
958    ///
959    /// TODO: will be deprecated sooner or later in favor of a method that does not move the
960    /// resource on failure.
961    ///
962    // #[deprecated = "Use leak_box_at and initialize it with the value. This does not move the value in the failure case."]
963    #[expect(clippy::mut_from_ref)] // This is an allocator.
964    pub fn leak_at<V>(&self, val: V, level: Level) -> Result<(&mut V, Level), LeakError<V>> {
965        let alloc = match self.get_at::<V>(level) {
966            Ok(alloc) => alloc,
967            Err(err) => return Err(LeakError::new(val, err)),
968        };
969
970        // SAFETY: Just allocated this for a `V`.
971        let level = alloc.level;
972        let mutref = unsafe { alloc.leak(val) };
973        Ok((mutref, level))
974    }
975}
976
977impl BumpSlice {
978    /// Construct a bump allocator into an existing dynamically sized arena of memory.
979    ///
980    /// # Usage
981    ///
982    /// This way you may re-use storage from some arbitrary existing span of memory, provided it has
983    /// at least enough room to hold an aligned header.
984    ///
985    /// ```
986    /// use core::mem::MaybeUninit;
987    /// use static_alloc::bump::BumpSlice;
988    /// # fn example() -> Option<()> {
989    ///
990    /// let mut buffer = MaybeUninit::<[u8; 256]>::uninit();
991    /// let bump = BumpSlice::from_memory(buffer.as_mut())?;
992    ///
993    /// // Slightly less than 256 free bytes of memory to use.
994    /// // Exact number is unstable and depends on the align of `buffer`.
995    /// let allocated_slice = bump.get_slice::<u32>(50)?;
996    ///
997    /// # Some(()) }
998    /// ```
999    pub fn from_memory(data: &mut [MaybeUninit<u8>]) -> Option<&'_ mut Self> {
1000        // First we must write a `Header` structure, the available storage then follows it. To do
1001        // this we create a temporary bump allocator with an external header.
1002        let start_addr = {
1003            let tmp_header = Header::empty();
1004            let data = UnsafeCell::from_mut(data);
1005
1006            let alloc = BumpView {
1007                header: &tmp_header,
1008                storage: &*data,
1009            };
1010
1011            // Initialize a header at some valid location in this data.
1012            let mut initialized_header = alloc.leak_box::<Header>(Header::empty())?;
1013            <*mut Header>::addr(&mut *initialized_header)
1014        };
1015
1016        // Time to drop the temporary allocator.
1017        let offset = start_addr - <*mut [_]>::addr(data);
1018        // This has the right address and provenance, but wrong len metadata for a `BumpSlice`.
1019        let bump_slice = &mut data[offset..];
1020
1021        let len = bump_slice.len() - core::mem::size_of::<Header>();
1022        let data = core::ptr::slice_from_raw_parts_mut(bump_slice.as_mut_ptr(), len);
1023
1024        Some(unsafe { &mut *(data as *mut BumpSlice) })
1025    }
1026
1027    /// Reset the bump allocator.
1028    ///
1029    /// Requires a mutable reference, as no allocations can be active when doing it. This behaves
1030    /// as if a fresh instance was assigned but it does not overwrite the bytes in the backing
1031    /// storage. (You can unsafely rely on this).
1032    ///
1033    /// ## Usage
1034    ///
1035    /// ```
1036    /// # use static_alloc::bump::{Bump, BumpSlice};
1037    /// let mut stack_buf = Bump::<usize>::uninit();
1038    /// let stack_buf = stack_buf.as_mut_bump_slice().unwrap();
1039    ///
1040    /// let bytes = stack_buf.leak(0usize.to_be_bytes()).unwrap();
1041    /// // Now the bump allocator is full.
1042    /// assert!(stack_buf.leak(0u8).is_err());
1043    ///
1044    /// // We can reuse if we are okay with forgetting the previous value.
1045    /// stack_buf.reset();
1046    /// let val = stack_buf.leak(0usize).unwrap();
1047    /// ```
1048    ///
1049    /// Trying to use the previous value does not work, as the stack is still borrowed. Note that
1050    /// any user unsafely tracking the lifetime must also ensure this through proper lifetimes that
1051    /// guarantee that borrows are alive for appropriate times.
1052    ///
1053    /// ```compile_fail
1054    /// // error[E0502]: cannot borrow `stack_buf` as mutable because it is also borrowed as immutable
1055    /// # use static_alloc::bump::{Bump, BumpSlice};
1056    /// let mut stack_buf = Bump::<usize>::uninit();
1057    /// let stack_buf = stack_buf.as_mut_bump_slice().unwrap();
1058    ///
1059    /// let bytes = stack_buf.leak(0usize).unwrap();
1060    /// //          --------- immutably borrow occurs here
1061    /// stack_buf.reset();
1062    /// // ^^^^^^^ mutable borrow occurs here.
1063    /// let other = stack_buf.leak(0usize).unwrap();
1064    ///
1065    /// *bytes += *other;
1066    /// // ------------- immutable borrow later used here
1067    /// ```
1068    pub fn reset(&mut self) {
1069        self.header = Header::empty();
1070    }
1071
1072    pub(crate) fn as_view(&self) -> BumpView<'_> {
1073        BumpView {
1074            header: &self.header,
1075            storage: &self.storage,
1076        }
1077    }
1078
1079    /// Returns capacity of this allocator.
1080    ///
1081    /// This is how many *bytes* can be allocated within this allocator in total, with no
1082    /// information about the currently consumed count.
1083    pub const fn capacity(&self) -> usize {
1084        self.storage.get().len()
1085    }
1086
1087    /// Get a raw pointer to the data.
1088    ///
1089    /// Note that *any* use of the pointer must be done with extreme care as it may invalidate
1090    /// existing references into the allocated region. Furthermore, bytes may not be initialized.
1091    /// The length of the valid region is [`BumpSlice::capacity`].
1092    ///
1093    /// Prefer [`Self::get_unchecked`] for reconstructing a prior allocation.
1094    pub fn data_ptr(&self) -> NonNull<u8> {
1095        NonNull::from(&self.storage).cast()
1096    }
1097
1098    /// Allocate a region of memory.
1099    ///
1100    /// This is a safe alternative to [GlobalAlloc::alloc](#impl-GlobalAlloc).
1101    ///
1102    /// # Panics
1103    /// This function will panic if the requested layout has a size of `0`. For the use in a
1104    /// `GlobalAlloc` this is explicitely forbidden to request and would allow any behaviour but we
1105    /// instead strictly check it.
1106    pub fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
1107        self.as_view().alloc(layout)
1108    }
1109
1110    /// Try to allocate some layout with a precise base location.
1111    ///
1112    /// The base location is the currently consumed byte count, without correction for the
1113    /// alignment of the allocation. This will succeed if it can be allocate exactly at the
1114    /// expected location.
1115    ///
1116    /// # Panics
1117    /// This function may panic if the provided `level` is from a different slab.
1118    pub fn alloc_at(&self, layout: Layout, level: Level) -> Result<Allocation<'_>, Failure> {
1119        self.as_view().alloc_at(layout, level)
1120    }
1121
1122    /// Get an allocation with detailed layout.
1123    ///
1124    /// Provides an [`Uninit`] wrapping several aspects of initialization in a safe interface,
1125    /// bound by the lifetime of the reference to the allocator.
1126    ///
1127    /// [`Uninit`]: ../uninit/struct.Uninit.html
1128    pub fn get_layout(&self, layout: Layout) -> Option<Allocation<'_>> {
1129        self.as_view().get_layout(layout)
1130    }
1131
1132    /// Get an allocation with detailed layout at a specific level.
1133    ///
1134    /// Provides an [`Uninit`] wrapping several aspects of initialization in a safe interface,
1135    /// bound by the lifetime of the reference to the allocator.
1136    ///
1137    /// Since the underlying allocation is the same, it would be `unsafe` but justified to fuse
1138    /// this allocation with the preceding or succeeding one.
1139    ///
1140    /// [`Uninit`]: ../uninit/struct.Uninit.html
1141    pub fn get_layout_at(&self, layout: Layout, at: Level) -> Result<Allocation<'_>, Failure> {
1142        self.as_view().get_layout_at(layout, at)
1143    }
1144
1145    /// Get an allocation for a specific type.
1146    ///
1147    /// It is not yet initialized but provides a safe interface for that initialization.
1148    ///
1149    /// ## Usage
1150    ///
1151    /// ```
1152    /// # use static_alloc::bump::{Bump, BumpSlice};
1153    /// use core::cell::{Ref, RefCell};
1154    ///
1155    /// let backing: Bump<[Ref<'static, usize>; 1]> = Bump::uninit();
1156    /// let slab = backing.as_bump_slice().unwrap();
1157    ///
1158    /// let data = RefCell::new(0xff);
1159    ///
1160    /// // We can place a `Ref` here but we did not yet.
1161    /// let alloc = slab.get::<Ref<usize>>().unwrap();
1162    /// let cell_ref = unsafe {
1163    ///     alloc.leak(data.borrow())
1164    /// };
1165    ///
1166    /// assert_eq!(**cell_ref, 0xff);
1167    /// ```
1168    pub fn get<V>(&self) -> Option<Allocation<'_, V>> {
1169        self.as_view().get()
1170    }
1171
1172    /// Get an allocation for a specific type at a specific level.
1173    ///
1174    /// See [`get`] for usage.
1175    ///
1176    /// [`get`]: #method.get
1177    pub fn get_at<V>(&self, level: Level) -> Result<Allocation<'_, V>, Failure> {
1178        self.as_view().get_at(level)
1179    }
1180
1181    /// Get an allocation for a slice of a type.
1182    ///
1183    /// Returns `None` if the allocation fails (see [`Self::get`]) or if the slice layout can not be
1184    /// computed due to an overflow with this size.
1185    ///
1186    /// # Examples
1187    ///
1188    /// ```
1189    /// # use static_alloc::bump::{Bump, BumpSlice};
1190    ///
1191    /// let backing: Bump<[usize; 6]> = Bump::uninit();
1192    /// let slab = backing.as_bump_slice().unwrap();
1193    ///
1194    /// let first = slab.get_slice::<usize>(4).unwrap();
1195    /// let second = slab.get_slice::<usize>(2).unwrap();
1196    /// assert!(slab.get_slice::<usize>(1).is_none());
1197    ///
1198    /// assert_eq!(first.ptr.len(), 4);
1199    /// assert_eq!(second.ptr.len(), 2);
1200    /// ```
1201    ///
1202    /// ```
1203    /// # use static_alloc::bump::{Bump, BumpSlice};
1204    ///
1205    /// let backing: Bump<[usize; 1]> = Bump::uninit();
1206    /// let slab = backing.as_bump_slice().unwrap();
1207    ///
1208    /// let lots_of_empty = slab.get_slice::<()>(usize::MAX).unwrap();
1209    /// assert_eq!(lots_of_empty.ptr.len(), usize::MAX);
1210    /// ```
1211    ///
1212    /// ```
1213    /// # use static_alloc::bump::{Bump, BumpSlice};
1214    ///
1215    /// let backing: Bump<[usize; 1]> = Bump::uninit();
1216    /// let slab = backing.as_bump_slice().unwrap();
1217    ///
1218    /// let _exhaust = slab.get_slice::<usize>(1).unwrap();
1219    /// assert!(slab.get_slice::<usize>(1).is_none());
1220    /// let empty_slice = slab.get_slice::<usize>(0).unwrap();
1221    /// ```
1222    pub fn get_slice<V>(&self, len: usize) -> Option<Allocation<'_, [V]>> {
1223        self.as_view().get_slice(len)
1224    }
1225
1226    /// Move a value into an owned allocation.
1227    ///
1228    /// For safely initializing a value _after_ a successful allocation, see [`LeakBox::write`].
1229    ///
1230    /// [`LeakBox::write`]: ../leaked/struct.LeakBox.html#method.write
1231    ///
1232    /// ## Usage
1233    ///
1234    /// This can be used to push the value into a caller provided stack buffer where it lives
1235    /// longer than the current stack frame. For example, you might create a linked list with a
1236    /// dynamic number of values living in the frame below while still being dropped properly. This
1237    /// is impossible to do with a return value.
1238    ///
1239    /// ```
1240    /// # use static_alloc::bump::{Bump, BumpSlice};
1241    /// # use static_alloc::leaked::LeakBox;
1242    /// fn rand() -> usize { 4 }
1243    ///
1244    /// enum Chain<'buf, T> {
1245    ///    Tail,
1246    ///    Link(T, LeakBox<'buf, Self>),
1247    /// }
1248    ///
1249    /// fn make_chain<T>(buf: &BumpSlice, mut new_node: impl FnMut() -> T)
1250    ///     -> Option<Chain<'_, T>>
1251    /// {
1252    ///     let count = rand();
1253    ///     let mut chain = Chain::Tail;
1254    ///     for _ in 0..count {
1255    ///         let node = new_node();
1256    ///         chain = Chain::Link(node, buf.leak_box(chain)?);
1257    ///     }
1258    ///     Some(chain)
1259    /// }
1260    ///
1261    /// struct Node (usize);
1262    /// impl Drop for Node {
1263    ///     fn drop(&mut self) {
1264    ///         println!("Dropped {}", self.0);
1265    ///     }
1266    /// }
1267    /// let mut counter = 0..;
1268    /// let new_node = || Node(counter.next().unwrap());
1269    ///
1270    /// let buffer: Bump<[u8; 128]> = Bump::uninit();
1271    /// let buffer = buffer.as_bump_slice().unwrap();
1272    /// let head = make_chain(buffer, new_node).unwrap();
1273    ///
1274    /// // Prints the message in reverse order.
1275    /// // Dropped 3
1276    /// // Dropped 2
1277    /// // Dropped 1
1278    /// // Dropped 0
1279    /// drop(head);
1280    /// ```
1281    pub fn leak_box<V>(&self, val: V) -> Option<LeakBox<'_, V>> {
1282        self.as_view().leak_box(val)
1283    }
1284
1285    /// Move a value into an owned allocation.
1286    ///
1287    /// See [`leak_box`] for usage.
1288    ///
1289    /// [`leak_box`]: #method.leak_box
1290    pub fn leak_box_at<V>(&self, val: V, level: Level) -> Result<LeakBox<'_, V>, Failure> {
1291        self.as_view().leak_box_at(val, level)
1292    }
1293
1294    /// Observe the current level.
1295    ///
1296    /// Keep in mind that concurrent usage of the same slab may modify the level before you are
1297    /// able to use it in `alloc_at`. Calling this method provides also no other guarantees on
1298    /// synchronization of memory accesses, only that the values observed by the caller are a
1299    /// monotonically increasing seequence while a shared reference exists.
1300    pub fn level(&self) -> Level {
1301        self.as_view().level()
1302    }
1303
1304    /// Get a pointer to an existing allocation at a specific level.
1305    ///
1306    /// The resulting pointer may be used to access an arbitrary allocation starting at the pointer
1307    /// (i.e. including additional allocations immediately afterwards) but the caller is
1308    /// responsible for ensuring that these accesses do not overlap other accesses. There must be
1309    /// no more life [`LeakBox`] to any allocation being accessed this way.
1310    ///
1311    /// # Safety
1312    ///
1313    /// - The level must refer to an existing allocation, i.e. it must previously have been
1314    ///   returned in [`Allocation::level`].
1315    /// - As a corollary, particular it must be in-bounds of the allocator's memory.
1316    /// - Another consequence, the result pointer must be aligned for the requested type.
1317    pub unsafe fn get_unchecked<V>(&self, level: Level) -> Allocation<'_, V> {
1318        // Safety: forwarding requirements.
1319        unsafe { self.as_view().get_unchecked(level) }
1320    }
1321
1322    /// Allocate a value for the lifetime of the allocator.
1323    ///
1324    /// The value is leaked in the sense that
1325    ///
1326    /// 1. the drop implementation of the allocated value is never called;
1327    /// 2. reusing the memory for another allocation in the same `Bump` requires manual unsafe code
1328    ///    to handle dropping and reinitialization.
1329    ///
1330    /// However, it does not mean that the underlying memory used for the allocated value is never
1331    /// reclaimed. If the `Bump` itself is a stack value then it will get reclaimed together with
1332    /// it.
1333    ///
1334    /// ## Safety notice
1335    ///
1336    /// It is important to understand that it is undefined behaviour to reuse the allocation for
1337    /// the *whole lifetime* of the returned reference. That is, dropping the allocation in-place
1338    /// while the reference is still within its lifetime comes with the exact same unsafety caveats
1339    /// as [`ManuallyDrop::drop`].
1340    ///
1341    /// ```
1342    /// # use static_alloc::bump::{Bump, BumpSlice};
1343    /// #[derive(Debug, Default)]
1344    /// struct FooBar {
1345    ///     // ...
1346    /// # _private: [u8; 1],
1347    /// }
1348    ///
1349    /// let local: Bump<[FooBar; 3]> = Bump::uninit();
1350    /// let local = local.as_bump_slice().unwrap();
1351    /// let one = local.leak(FooBar::default()).unwrap();
1352    ///
1353    /// // Dangerous but justifiable.
1354    /// let one = unsafe {
1355    ///     // Ensures there is no current mutable borrow.
1356    ///     core::ptr::drop_in_place(&mut *one);
1357    /// };
1358    /// ```
1359    ///
1360    /// ## Usage
1361    ///
1362    /// ```
1363    /// use static_alloc::bump::{Bump, BumpSlice};
1364    ///
1365    /// let local: Bump<[u64; 3]> = Bump::uninit();
1366    /// let local = local.as_bump_slice().unwrap();
1367    ///
1368    /// let one = local.leak(0_u64).unwrap();
1369    /// assert_eq!(*one, 0);
1370    /// *one = 42;
1371    /// ```
1372    ///
1373    /// ## Limitations
1374    ///
1375    /// Only sized values can be allocated in this manner for now, unsized values are blocked on
1376    /// stabilization of [`ptr::slice_from_raw_parts`]. We can not otherwise get a fat pointer to
1377    /// the allocated region.
1378    ///
1379    /// [`ptr::slice_from_raw_parts`]: https://github.com/rust-lang/rust/issues/36925
1380    /// [`ManuallyDrop::drop`]: https://doc.rust-lang.org/beta/std/mem/struct.ManuallyDrop.html#method.drop
1381    ///
1382    /// TODO: will be deprecated sooner or later in favor of a method that does not move the
1383    /// resource on failure.
1384    // #[deprecated = "Use leak_box and initialize it with the value. This does not move the value in the failure case."]
1385    #[expect(clippy::mut_from_ref)] // This is an allocator.
1386    pub fn leak<V>(&self, val: V) -> Result<&mut V, LeakError<V>> {
1387        match self.get::<V>() {
1388            // SAFETY: Just allocated this for a `V`.
1389            Some(alloc) => Ok(unsafe { alloc.leak(val) }),
1390            None => Err(LeakError::new(val, Failure::Exhausted)),
1391        }
1392    }
1393
1394    /// Allocate a value with a precise location.
1395    ///
1396    /// See [`leak`] for basics on allocation of values.
1397    ///
1398    /// The level is an identifer for a base location (more at [`level`]). This will succeed if it
1399    /// can be allocate exactly at the expected location.
1400    ///
1401    /// This method will return the new level of the slab allocator. A next allocation at the
1402    /// returned level will be placed next to this allocation, only separated by necessary padding
1403    /// from alignment. In particular, this is the same strategy as applied for the placement of
1404    /// `#[repr(C)]` struct members. (Except for the final padding at the last member to the full
1405    /// struct alignment.)
1406    ///
1407    /// ## Usage
1408    ///
1409    /// ```
1410    /// use static_alloc::bump::{Bump, BumpSlice};
1411    ///
1412    /// let local: Bump<[u64; 3]> = Bump::uninit();
1413    /// let local = local.as_bump_slice().unwrap();
1414    ///
1415    /// let base = local.level();
1416    /// let (one, level) = local.leak_at(1_u64, base).unwrap();
1417    /// // Will panic when an allocation happens in between.
1418    /// let (two, _) = local.leak_at(2_u64, level).unwrap();
1419    ///
1420    /// assert_eq!((one as *const u64).wrapping_offset(1), two);
1421    /// ```
1422    ///
1423    /// [`leak`]: #method.leak
1424    /// [`level`]: #method.level
1425    ///
1426    /// TODO: will be deprecated sooner or later in favor of a method that does not move the
1427    /// resource on failure.
1428    ///
1429    // #[deprecated = "Use leak_box_at and initialize it with the value. This does not move the value in the failure case."]
1430    #[expect(clippy::mut_from_ref)] // This is an allocator.
1431    pub fn leak_at<V>(&self, val: V, level: Level) -> Result<(&mut V, Level), LeakError<V>> {
1432        let alloc = match self.get_at::<V>(level) {
1433            Ok(alloc) => alloc,
1434            Err(err) => return Err(LeakError::new(val, err)),
1435        };
1436
1437        // SAFETY: Just allocated this for a `V`.
1438        let level = alloc.level;
1439        let mutref = unsafe { alloc.leak(val) };
1440        Ok((mutref, level))
1441    }
1442}
1443
1444impl<'lt> BumpView<'lt> {
1445    pub fn alloc(self, layout: Layout) -> Option<NonNull<u8>> {
1446        Some(self.try_alloc(layout).ok()?.ptr)
1447    }
1448
1449    pub fn alloc_at(self, layout: Layout, level: Level) -> Result<Allocation<'lt>, Failure> {
1450        let Allocation {
1451            ptr,
1452            lifetime,
1453            level,
1454        } = self.try_alloc_at(layout, level.0)?;
1455
1456        Ok(Allocation {
1457            ptr: ptr.cast(),
1458            lifetime,
1459            level,
1460        })
1461    }
1462
1463    pub fn get_layout(self, layout: Layout) -> Option<Allocation<'lt>> {
1464        self.try_alloc(layout).ok()
1465    }
1466
1467    pub fn get_layout_at(self, layout: Layout, at: Level) -> Result<Allocation<'lt>, Failure> {
1468        self.try_alloc_at(layout, at.0)
1469    }
1470
1471    pub fn get<V>(self) -> Option<Allocation<'lt, V>> {
1472        if mem::size_of::<V>() == 0 {
1473            return Some(self.zst_fake_alloc());
1474        }
1475
1476        let layout = Layout::new::<V>();
1477        let Allocation {
1478            ptr,
1479            lifetime,
1480            level,
1481        } = self.try_alloc(layout).ok()?;
1482
1483        Some(Allocation {
1484            ptr: ptr.cast(),
1485            lifetime,
1486            level,
1487        })
1488    }
1489
1490    pub fn get_at<V>(self, level: Level) -> Result<Allocation<'lt, V>, Failure> {
1491        if mem::size_of::<V>() == 0 {
1492            let fake = self.zst_fake_alloc();
1493            // Note: zst_fake_alloc is a noop on the level, we may as well check after.
1494            if fake.level != level {
1495                return Err(Failure::Mismatch {
1496                    observed: fake.level,
1497                });
1498            }
1499            return Ok(fake);
1500        }
1501
1502        let layout = Layout::new::<V>();
1503        let Allocation {
1504            ptr,
1505            lifetime,
1506            level,
1507        } = self.try_alloc_at(layout, level.0)?;
1508
1509        Ok(Allocation {
1510            // It has exactly size and alignment for `V` as requested.
1511            ptr: ptr.cast(),
1512            lifetime,
1513            level,
1514        })
1515    }
1516
1517    pub fn get_slice<V>(&self, len: usize) -> Option<Allocation<'lt, [V]>> {
1518        if len == 0 {
1519            return Some(Allocation::for_empty_slice(self.level()));
1520        }
1521
1522        let layout = Layout::array::<V>(len).ok()?;
1523
1524        if layout.size() == 0 {
1525            // Synthesize the slice for this ZST.
1526            return Some(Allocation::for_zst_slice(len, self.level()));
1527        };
1528
1529        let alloc = self.get_layout(layout)?;
1530
1531        Some(Allocation {
1532            ptr: NonNull::slice_from_raw_parts(alloc.ptr.cast(), len),
1533            lifetime: alloc.lifetime,
1534            level: alloc.level,
1535        })
1536    }
1537
1538    pub fn leak_box<V>(self, val: V) -> Option<LeakBox<'lt, V>> {
1539        let Allocation { ptr, lifetime, .. } = self.get::<V>()?;
1540        Some(unsafe { LeakBox::new_from_raw_non_null(ptr, val, lifetime) })
1541    }
1542
1543    pub fn leak_box_at<V>(self, val: V, level: Level) -> Result<LeakBox<'lt, V>, Failure> {
1544        let Allocation { ptr, lifetime, .. } = self.get_at::<V>(level)?;
1545        Ok(unsafe { LeakBox::new_from_raw_non_null(ptr, val, lifetime) })
1546    }
1547
1548    pub fn level(&self) -> Level {
1549        Level(self.header.consumed.load(Ordering::SeqCst))
1550    }
1551
1552    /// # Safety
1553    ///
1554    /// - The level must refer to an existing allocation, i.e. it must previously have been
1555    ///   returned in [`Allocation::level`].
1556    /// - As a corollary, particular it must be in-bounds of the allocator's memory.
1557    /// - Another consequence, the result pointer must be aligned for the requested type.
1558    pub unsafe fn get_unchecked<V>(self, level: Level) -> Allocation<'lt, V> {
1559        debug_assert!(level.0 <= mem::size_of_val(self.storage));
1560
1561        debug_assert!(
1562            level <= self.level(),
1563            "Tried to access an allocation that does not yet exist"
1564        );
1565
1566        let base_ptr = self.storage.get().cast::<u8>();
1567        // SAFETY: `level.0` is in bounds as assert above, or by the caller by having provided an
1568        // existing allocation—all allocations we hand out are in bounds.
1569        let alloc = unsafe { base_ptr.add(level.0) };
1570        let ptr = NonNull::new(alloc).unwrap().cast::<V>();
1571
1572        debug_assert!(
1573            ptr.as_ptr().is_aligned(),
1574            "Tried to access an allocation with improper type"
1575        );
1576
1577        Allocation {
1578            level,
1579            lifetime: AllocTime::default(),
1580            ptr,
1581        }
1582    }
1583
1584    // FIXME: should take `NonZeroLayout`.
1585    pub(crate) fn try_alloc(self, layout: Layout) -> Result<Allocation<'lt>, Level> {
1586        // Guess the current level, this will fail when we try to access it and it isn't.
1587        let mut consumed = self.level().0;
1588        // FIXME: parts of the initial computation depends mostly on `layout` and `storage`, i.e.
1589        // not on the current level. It's not verified if LLVM moves these out of the loop and it's
1590        // doubtful since there's a CAS within it (`self.bump`). Rewrite to avoid this, e.g. a
1591        // 'qualified layout` type filled with specifics to our storage? Especially since we align
1592        // upwards which isn't a simple AND. However, calculating the last possible end-location and
1593        // then the last possible start, and then a simpler comparison would be.
1594        //
1595        // Speaking of this might motivate changing to storing the number of bytes left instead of
1596        // the number of bytes consumed. Then we have again an AND boundary with an addition for the
1597        // CAS update.
1598        loop {
1599            match self.try_alloc_at(layout, consumed) {
1600                Ok(alloc) => return Ok(alloc),
1601                Err(Failure::Exhausted) => return Err(Level(consumed)),
1602                Err(Failure::Mismatch { observed }) => consumed = observed.0,
1603            }
1604        }
1605    }
1606
1607    /// Try to allocate some layout with a precise base location.
1608    ///
1609    /// The base location is the currently consumed byte count, without correction for the
1610    /// alignment of the allocation. This will succeed if it can be allocate exactly at the
1611    /// expected location.
1612    ///
1613    /// # Panics
1614    /// This function panics if `expect_consumed` is larger than `length`.
1615    /// FIXME: should take `NonZeroLayout`.
1616    fn try_alloc_at(
1617        self,
1618        layout: Layout,
1619        expect_consumed: usize,
1620    ) -> Result<Allocation<'lt>, Failure> {
1621        assert!(layout.size() > 0);
1622        let length = self.storage.get().len();
1623        let base_ptr = self.storage.get().cast::<u8>();
1624
1625        let alignment = layout.align();
1626        let requested = layout.size();
1627
1628        // Ensure no overflows when calculating offets within.
1629        assert!(expect_consumed <= length);
1630
1631        let available = length.checked_sub(expect_consumed).unwrap();
1632        let ptr_to = base_ptr.wrapping_add(expect_consumed);
1633        let offset = ptr_to.align_offset(alignment);
1634
1635        if requested > available.saturating_sub(offset) {
1636            return Err(Failure::Exhausted); // exhausted
1637        }
1638
1639        // `size` can not be zero, saturation will thus always make this true.
1640        assert!(offset < available);
1641        let at_aligned = expect_consumed.checked_add(offset).unwrap();
1642        let new_consumed = at_aligned.checked_add(requested).unwrap();
1643        // new_consumed
1644        //    = consumed + offset + requested  [lines above]
1645        //   <= consumed + available  [bail out: exhausted]
1646        //   <= length  [first line of loop]
1647        // So it's ok to store `allocated` into `consumed`.
1648        assert!(new_consumed <= length);
1649        assert!(at_aligned < length);
1650
1651        // Try to actually allocate.
1652        match self.bump(expect_consumed, new_consumed) {
1653            Ok(()) => (),
1654            Err(observed) => {
1655                // Someone else was faster, if you want it then recalculate again.
1656                return Err(Failure::Mismatch {
1657                    observed: Level(observed),
1658                });
1659            }
1660        }
1661
1662        let aligned = unsafe {
1663            // SAFETY:
1664            // * `0 <= at_aligned < length` in bounds as checked above.
1665            base_ptr.byte_add(at_aligned)
1666        };
1667
1668        Ok(Allocation {
1669            ptr: NonNull::new(aligned).unwrap(),
1670            lifetime: AllocTime::default(),
1671            level: Level(new_consumed),
1672        })
1673    }
1674
1675    /// 'Allocate' a ZST.
1676    fn zst_fake_alloc<Z>(&self) -> Allocation<'lt, Z> {
1677        Allocation::for_zst(self.level())
1678    }
1679
1680    /// Try to bump the monotonic, atomic consume counter.
1681    ///
1682    /// This is the only place doing shared modification to `self.consumed`.
1683    ///
1684    /// Returns `Ok` if the consume counter was as expected. Monotonicty and atomicity guarantees
1685    /// to the caller that no overlapping range can succeed as well. This allocates the range to
1686    /// the caller.
1687    ///
1688    /// Returns the observed consume counter in an `Err` if it was not as expected.
1689    ///
1690    /// ## Panics
1691    /// This function panics if either argument exceeds the byte length of the underlying memory.
1692    /// It also panics if the expected value is larger than the new value.
1693    fn bump(&self, expect_consumed: usize, new_consumed: usize) -> Result<(), usize> {
1694        assert!(expect_consumed <= new_consumed);
1695        assert!(new_consumed <= self.storage.get().len());
1696        self.header.bump(expect_consumed, new_consumed)
1697    }
1698}
1699
1700impl Header {
1701    const fn empty() -> Self {
1702        Header {
1703            consumed: AtomicUsize::new(0),
1704        }
1705    }
1706
1707    fn bump(&self, expect_consumed: usize, new_consumed: usize) -> Result<(), usize> {
1708        self.consumed
1709            .compare_exchange(
1710                expect_consumed,
1711                new_consumed,
1712                Ordering::SeqCst,
1713                Ordering::SeqCst,
1714            )
1715            .map(drop)
1716    }
1717}
1718
1719impl<'alloc, T> Allocation<'alloc, T> {
1720    /// Write a value into the allocation and leak it.
1721    ///
1722    /// ## Safety
1723    ///
1724    /// Must have been allocated for a layout that fits the layout of T previously. The pointer
1725    /// must not be aliased.
1726    ///
1727    /// ## Usage
1728    ///
1729    /// Consider the alternative [`Bump::leak`] to safely allocate and directly leak a value.
1730    ///
1731    /// [`Bump::leak`]: struct.Bump.html#method.leak
1732    pub unsafe fn leak(self, val: T) -> &'alloc mut T {
1733        // Safety: The pointer is valid for a write as per caller.
1734        unsafe { core::ptr::write(self.ptr.as_ptr(), val) };
1735        // Safety: The pointer is not borrowed and valid as guaranteed by the caller.
1736        unsafe { &mut *self.ptr.as_ptr() }
1737    }
1738
1739    /// Write a value into the allocation and own it.
1740    ///
1741    /// ## Safety
1742    ///
1743    /// Must have been allocated for a layout that fits the layout of T previously. The pointer
1744    /// must not be aliased.
1745    ///
1746    /// ## Usage
1747    ///
1748    /// Consider the alternative [`Bump::leak`] to safely allocate and directly leak a value.
1749    ///
1750    /// [`Bump::leak`]: struct.Bump.html#method.leak
1751    pub unsafe fn boxed(self, val: T) -> LeakBox<'alloc, T> {
1752        // The pointer is not aliased and valid as guaranteed by the caller.
1753        unsafe { core::ptr::write(self.ptr.as_ptr(), val) };
1754        // Safety: the instance is valid, was just initialized.
1755        unsafe { LeakBox::from_raw(self.ptr.as_ptr()) }
1756    }
1757
1758    /// Convert this into a mutable reference to an uninitialized slot.
1759    ///
1760    /// ## Safety
1761    ///
1762    /// Must have been allocated for a layout that fits the layout of T previously.
1763    pub unsafe fn uninit(self) -> &'alloc mut MaybeUninit<T> {
1764        unsafe { &mut *self.ptr.cast().as_ptr() }
1765    }
1766
1767    /// An 'allocation' for an arbitrary ZST, at some arbitrary level.
1768    pub(crate) fn for_zst(level: Level) -> Self {
1769        assert!(mem::size_of::<T>() == 0);
1770        // If `Z` is a ZST, then the stride of any array is equal to 0. Thus, all arrays and slices
1771        // havee the same layout which only depends on the alignment. If we need a storage for this
1772        // ZST we just take one of those as our base 'allocation' which can also never be aliased.
1773        let alloc: &[T; 0] = &[];
1774
1775        Allocation {
1776            ptr: NonNull::from(alloc).cast(),
1777            lifetime: AllocTime::default(),
1778            level,
1779        }
1780    }
1781
1782    pub(crate) fn for_zst_slice(len: usize, level: Level) -> Allocation<'alloc, [T]> {
1783        assert!(mem::size_of::<T>() == 0);
1784        let alloc: &[T; 0] = &[];
1785
1786        Allocation {
1787            ptr: NonNull::slice_from_raw_parts(NonNull::from(alloc).cast(), len),
1788            lifetime: AllocTime::default(),
1789            level,
1790        }
1791    }
1792
1793    pub(crate) fn for_empty_slice(level: Level) -> Allocation<'alloc, [T]> {
1794        let alloc: &[T; 0] = &[];
1795
1796        Allocation {
1797            ptr: NonNull::from(alloc),
1798            lifetime: AllocTime::default(),
1799            level,
1800        }
1801    }
1802}
1803
1804impl<T> LeakError<T> {
1805    fn new(val: T, failure: Failure) -> Self {
1806        LeakError { val, failure }
1807    }
1808
1809    /// Inspect the cause of this error.
1810    pub fn kind(&self) -> Failure {
1811        self.failure
1812    }
1813
1814    /// Retrieve the value that could not be allocated.
1815    pub fn into_inner(self) -> T {
1816        self.val
1817    }
1818}
1819
1820// SAFETY: at most one thread gets a pointer to each chunk of data.
1821unsafe impl<T> Sync for Bump<T> {}
1822
1823// SAFETY: at most one thread gets a pointer to each chunk of data.
1824unsafe impl Sync for BumpView<'_> {}
1825unsafe impl Send for BumpView<'_> {}
1826
1827unsafe impl<T> GlobalAlloc for Bump<T> {
1828    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
1829        // Safety: just handing over arguments exactly as is. These two allocators are 'compatible'
1830        // in the sense they hold onto the same value handles.
1831        unsafe { GlobalAlloc::alloc(&self.as_view(), layout) }
1832    }
1833
1834    unsafe fn realloc(&self, ptr: *mut u8, current: Layout, new_size: usize) -> *mut u8 {
1835        // Safety: just handing over arguments exactly as is. These two allocators are 'compatible'
1836        // in the sense they hold onto the same value handles.
1837        unsafe { GlobalAlloc::realloc(&self.as_view(), ptr, current, new_size) }
1838    }
1839
1840    unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
1841        // We are a slab allocator and do not deallocate.
1842    }
1843}
1844
1845unsafe impl GlobalAlloc for &'static BumpSlice {
1846    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
1847        // Safety: just handing over arguments exactly as is. These two allocators are 'compatible'
1848        // in the sense they hold onto the same value handles.
1849        unsafe { GlobalAlloc::alloc(&self.as_view(), layout) }
1850    }
1851
1852    unsafe fn realloc(&self, ptr: *mut u8, current: Layout, new_size: usize) -> *mut u8 {
1853        // Safety: just handing over arguments exactly as is. These two allocators are 'compatible'
1854        // in the sense they hold onto the same value handles.
1855        unsafe { GlobalAlloc::realloc(&self.as_view(), ptr, current, new_size) }
1856    }
1857
1858    unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
1859        // We are a slab allocator and do not deallocate.
1860    }
1861}
1862
1863unsafe impl GlobalAlloc for BumpView<'_> {
1864    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
1865        BumpView::alloc(*self, layout)
1866            .map(NonNull::as_ptr)
1867            .unwrap_or_else(null_mut)
1868    }
1869
1870    unsafe fn realloc(&self, ptr: *mut u8, current: Layout, new_size: usize) -> *mut u8 {
1871        let current = NonZeroLayout::from_layout(current.into()).unwrap();
1872        // Safety: As required of the caller, `new_size` is greater than 0.
1873        let new_size = unsafe { core::num::NonZeroUsize::new_unchecked(new_size) };
1874
1875        let target = match layout_reallocated(current, new_size) {
1876            Some(target) => target,
1877            None => return core::ptr::null_mut(),
1878        };
1879
1880        // Construct an allocation. This is not safe in general but the lifetime is not important.
1881        let reconstructed = alloc_traits::Allocation {
1882            // Safety: `ptr` is currently allocated via this allocator, i.e. non-null.
1883            ptr: unsafe { NonNull::new_unchecked(ptr) },
1884            layout: current,
1885            lifetime: AllocTime::default(),
1886        };
1887
1888        // Safety: satisfies our own invariants.
1889        unsafe { alloc_traits::LocalAlloc::realloc(self, reconstructed, target) }
1890            .map(|alloc| alloc.ptr.as_ptr())
1891            .unwrap_or_else(core::ptr::null_mut)
1892    }
1893
1894    unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
1895        // We are a slab allocator and do not deallocate.
1896    }
1897}
1898
1899fn layout_reallocated(
1900    layout: NonZeroLayout,
1901    target: core::num::NonZeroUsize,
1902) -> Option<NonZeroLayout> {
1903    // This may not be a valid layout.
1904    let layout = Layout::from_size_align(target.get(), layout.align()).ok()?;
1905    // This must succeed though, as the size was non-zero.
1906    Some(NonZeroLayout::from_layout(layout.into()).unwrap())
1907}
1908
1909unsafe impl<'alloc, T> LocalAlloc<'alloc> for Bump<T> {
1910    fn alloc(&'alloc self, layout: NonZeroLayout) -> Option<alloc_traits::Allocation<'alloc>> {
1911        let raw_alloc = self.get_layout(layout.into())?;
1912        Some(alloc_traits::Allocation {
1913            ptr: raw_alloc.ptr,
1914            layout,
1915            lifetime: AllocTime::default(),
1916        })
1917    }
1918
1919    unsafe fn realloc(
1920        &'alloc self,
1921        alloc: alloc_traits::Allocation<'alloc>,
1922        layout: NonZeroLayout,
1923    ) -> Option<alloc_traits::Allocation<'alloc>> {
1924        if alloc.ptr.as_ptr() as usize % layout.align() == 0 && alloc.layout.size() >= layout.size()
1925        {
1926            // Obvious fit, nothing to do.
1927            return Some(alloc_traits::Allocation {
1928                ptr: alloc.ptr,
1929                layout,
1930                lifetime: alloc.lifetime,
1931            });
1932        }
1933
1934        // TODO: we could try to allocate at the exact level that the allocation ends. If this
1935        // succeeds, there is no copying necessary. This was the point of `Level` anyways.
1936
1937        let new_alloc = LocalAlloc::alloc(self, layout)?;
1938
1939        // Safety:
1940        // - the old allocation is valid for the old size, as required of the caller.
1941        // - the old allocation is valid for reads as it is an allocation of the allocator.
1942        // - the new allocation is valid for the new size.
1943        // - the new allocation is valid for writes as it was successful.
1944        // - our effective copy is at most the old and new size.
1945        unsafe {
1946            core::ptr::copy_nonoverlapping(
1947                alloc.ptr.as_ptr(),
1948                new_alloc.ptr.as_ptr(),
1949                layout.size().min(alloc.layout.size()).into(),
1950            );
1951        }
1952
1953        // No dealloc.
1954        Some(new_alloc)
1955    }
1956
1957    unsafe fn dealloc(&'alloc self, _: alloc_traits::Allocation<'alloc>) {
1958        // We are a slab allocator and do not deallocate.
1959    }
1960}
1961
1962unsafe impl<'alloc> LocalAlloc<'alloc> for BumpView<'alloc> {
1963    fn alloc(&'alloc self, layout: NonZeroLayout) -> Option<alloc_traits::Allocation<'alloc>> {
1964        let raw_alloc = self.get_layout(layout.into())?;
1965        Some(alloc_traits::Allocation {
1966            ptr: raw_alloc.ptr,
1967            layout,
1968            lifetime: AllocTime::default(),
1969        })
1970    }
1971
1972    // TODO: alloc zeroed if the constructor was `Self::zeroed()`
1973
1974    /// Reallocates if the layout is strictly smaller and the allocation aligned.
1975    ///
1976    /// Note that this may succeed spuriously if the previous allocation is incidentally aligned to
1977    /// a larger alignment than had been request.
1978    ///
1979    /// Also not, reallocating to a smaller layout is NOT useless.
1980    ///
1981    /// It confirms that this allocator does not need the allocated layout to re/deallocate.
1982    /// Otherwise, even reallocating to a strictly smaller layout would be impossible without
1983    /// storing the prior layout.
1984    unsafe fn realloc(
1985        &'alloc self,
1986        alloc: alloc_traits::Allocation<'alloc>,
1987        layout: NonZeroLayout,
1988    ) -> Option<alloc_traits::Allocation<'alloc>> {
1989        if alloc.ptr.as_ptr() as usize % layout.align() == 0 && alloc.layout.size() >= layout.size()
1990        {
1991            // Obvious fit, nothing to do.
1992            return Some(alloc_traits::Allocation {
1993                ptr: alloc.ptr,
1994                layout,
1995                lifetime: alloc.lifetime,
1996            });
1997        }
1998
1999        // TODO: we could try to allocate at the exact level that the allocation ends. If this
2000        // succeeds, there is no copying necessary. This was the point of `Level` anyways.
2001
2002        let new_alloc = LocalAlloc::alloc(self, layout)?;
2003
2004        // Safety:
2005        // - the old allocation is valid for the old size, as required of the caller.
2006        // - the old allocation is valid for reads as it is an allocation of the allocator.
2007        // - the new allocation is valid for the new size.
2008        // - the new allocation is valid for writes as it was successful.
2009        // - our effective copy is at most the old and new size.
2010        unsafe {
2011            core::ptr::copy_nonoverlapping(
2012                alloc.ptr.as_ptr(),
2013                new_alloc.ptr.as_ptr(),
2014                layout.size().min(alloc.layout.size()).into(),
2015            );
2016        }
2017
2018        // No dealloc.
2019        Some(new_alloc)
2020    }
2021
2022    unsafe fn dealloc(&'alloc self, _: alloc_traits::Allocation<'alloc>) {
2023        // We are a slab allocator and do not deallocate.
2024    }
2025}
2026
2027#[cfg(test)]
2028mod tests {
2029    use super::*;
2030
2031    #[test]
2032    fn zst_no_drop() {
2033        #[derive(Debug)]
2034        struct PanicOnDrop;
2035
2036        impl Drop for PanicOnDrop {
2037            fn drop(&mut self) {
2038                panic!("No instance of this should ever get dropped");
2039            }
2040        }
2041
2042        let alloc = Bump::<()>::uninit();
2043        let _ = alloc.leak(PanicOnDrop).unwrap();
2044    }
2045}