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