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