Skip to main content

InlineBacked

Struct InlineBacked 

Source
pub struct InlineBacked<const N: usize> { /* private fields */ }
Expand description

Fixed-size inline storage backing.

The N bytes are stored inline in the struct, aligned to MAX_ALIGN. Allocations bump a cursor through this buffer; deallocation is a no-op. Reset via reset (requires &mut self).

N MUST be a multiple of core::mem::align_of::<usize>(); constructing with any other N is a compile-time error (const _: () = assert!(…) inside new).

§API-misuse compile-failures (pinned)

N must satisfy N % core::mem::align_of::<usize>() == 0. On the 32- and 64-bit targets this crate supports, align_of::<usize>() is 4 or 8 respectively, so N = 7 is never valid. The const assert (ASSERT_N_ALIGNED) fires at the call site of new():

// FAILS TO COMPILE: 7 is not a multiple of align_of::<usize>()
// on any supported target, so `ASSERT_N_ALIGNED` panics at const
// evaluation inside `InlineBacked::<7>::new()`.
use forge_alloc::InlineBacked;
let _ = InlineBacked::<7>::new();

§Move invariant (structure-relative backing)

base() returns a pointer derived from &self.storage, which lives inside the struct itself. Moving an InlineBacked (return by value, mem::swap, Box::new, putting it into a container that reallocates, etc.) relocates its inline storage to a new address. After such a move base() correctly reflects the new location, but any pointer previously returned from allocate is now dangling — it points at the old, now-deallocated stack slot or heap cell.

Wrappers that store an InlineBacked (e.g. BumpArena<InlineBacked<N>>) must NOT cache base() at construction; they must re-query on every allocation. The wrappers in this crate family follow that discipline. Raw callers who hold their own NonNull<u8> between allocate sites are responsible for pinning the InlineBacked (e.g. via Pin<Box<…>> or by keeping it in a local that the borrow checker proves is not moved) before issuing the allocation.

§Thread safety

Send: yes — the storage is owned (auto-derived; both UnsafeCell fields hold Send payloads). Sync: NO. The cursor uses UnsafeCell so that Allocator::allocate can take &self; concurrent &self allocation would race on the cursor. UnsafeCell<T> is !Sync regardless of T, which gives us the right behavior without any extra marker field. If you need cross-thread allocation use a higher-layer wrapper that adds atomicity (e.g. SharedBumpArena).

Implementations§

Source§

impl<const N: usize> InlineBacked<N>

Source

pub const fn new() -> Self

Construct empty inline storage.

Compile-time enforces that N is a multiple of core::mem::align_of::<usize>().

Source

pub fn allocated(&self) -> usize

Bytes already allocated from this backing.

Source

pub const fn capacity(&self) -> usize

Capacity in bytes — always N.

Source

pub fn remaining(&self) -> usize

Bytes remaining for allocation.

Source

pub fn reset(&mut self)

Reset the cursor to 0, reclaiming all allocated memory.

§Safety

All previously issued pointers become invalid. The caller is responsible for ensuring no outstanding pointer is read or written after this call. The &mut self receiver and BumpDeallocator<'a> lifetime patterns enforce this at compile time for Box-style usage; raw allocate callers must enforce it themselves.

Trait Implementations§

Source§

impl<const N: usize> Allocator for InlineBacked<N>

Source§

fn allocate(&self, layout: NonZeroLayout) -> Result<NonNull<[u8]>, AllocError>

Allocate a block satisfying layout. The returned slice’s length is at least layout.size() but may be larger.
Source§

fn capacity_bytes(&self) -> Option<usize>

Total bytes this allocator can issue, if bounded. None for unbounded allocators like System. Used by Watermark to compute thresholds.
Source§

fn allocate_zeroed( &self, layout: NonZeroLayout, ) -> Result<NonNull<[u8]>, AllocError>

Allocate a zero-initialized block.
Source§

unsafe fn grow( &self, ptr: NonNull<u8>, old: NonZeroLayout, new: NonZeroLayout, ) -> Result<NonNull<[u8]>, AllocError>

Grow an allocation in place if possible, otherwise allocate-copy-free. Read more
Source§

unsafe fn shrink( &self, ptr: NonNull<u8>, old: NonZeroLayout, new: NonZeroLayout, ) -> Result<NonNull<[u8]>, AllocError>

Shrink an allocation in place if possible, otherwise allocate-copy-free. Read more
Source§

fn reset(&mut self) -> Result<(), AllocError>

Reclaim everything previously allocated. Default impl returns AllocError — only arena-style allocators implement a meaningful reset. Read more
Source§

unsafe fn usable_size( &self, _ptr: NonNull<u8>, _layout: NonZeroLayout, ) -> Option<usize>

Usable size of an existing allocation, if the allocator can report it. Defaults to None — implementors that track usable size override. Read more
Source§

fn corruption_events(&self) -> u64

Detected freelist / metadata corruption events observed by this allocator since construction. Read more
Source§

impl<const N: usize> Deallocator for InlineBacked<N>

Source§

unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: NonZeroLayout)

Release a previously allocated block. Read more
Source§

impl<const N: usize> Default for InlineBacked<N>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<const N: usize> FixedRange for InlineBacked<N>

Source§

fn base(&self) -> NonNull<u8>

First byte of the owned address range. Read more
Source§

fn size(&self) -> usize

Length in bytes of the owned address range. Read more
Source§

fn commit(&self, offset: usize, len: usize) -> Result<(), AllocError>

Ensure the bytes [offset, offset + len) (relative to base) are backed by committed, writable memory before a consumer writes through them. Read more
Source§

fn contains(&self, ptr: NonNull<u8>) -> bool

Whether ptr lies within [base, base + size). Read more

Auto Trait Implementations§

§

impl<const N: usize> !Freeze for InlineBacked<N>

§

impl<const N: usize> !RefUnwindSafe for InlineBacked<N>

§

impl<const N: usize> !Sync for InlineBacked<N>

§

impl<const N: usize> Send for InlineBacked<N>

§

impl<const N: usize> Unpin for InlineBacked<N>

§

impl<const N: usize> UnsafeUnpin for InlineBacked<N>

§

impl<const N: usize> UnwindSafe for InlineBacked<N>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.