pub trait FixedRange {
// Required methods
fn base(&self) -> NonNull<u8>;
fn size(&self) -> usize;
// Provided methods
fn commit(&self, offset: usize, len: usize) -> Result<(), AllocError> { ... }
fn contains(&self, ptr: NonNull<u8>) -> bool { ... }
}Expand description
Required Methods§
Sourcefn base(&self) -> NonNull<u8>
fn base(&self) -> NonNull<u8>
First byte of the owned address range.
Concurrency contract: base (and size) must be
callable concurrently from multiple threads through a shared &self
without data races — i.e. they must not mutate through &self. A
thread-safe consumer such as SharedBumpArena relies on this to be
Sync while its backing is merely Send (not Sync): it only ever
calls base()/size() on the shared backing, never an interior-
mutating method. All in-tree backings satisfy this (these are pure
reads of an immutable field).
Provided Methods§
Sourcefn commit(&self, offset: usize, len: usize) -> Result<(), AllocError>
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.
The default is a no-op returning Ok(()): most backings hand back
memory that is already writable (InlineBacked’s inline array, a
mmap’d region under Unix demand-paging, an eagerly-committed
VirtualAlloc). The hook exists for backings that reserve address
space without committing it — currently only a lazy_commit
MmapBacked on
Windows — where a write to an uncommitted page would fault. A
cursor-advancing consumer (e.g. BumpArena) calls this as its
cursor crosses into new pages, and propagates the Err as an
allocation failure rather than letting the OS decline a reservation
turn into a hard access violation.
§Contract
[offset, offset + len)must lie within[0, size()).- On
Err(AllocError)the caller must treat the region as not committed and must not write through[offset, offset + len). - Idempotent and monotonic: committing a range that is already committed succeeds without side effects.
Sourcefn contains(&self, ptr: NonNull<u8>) -> bool
fn contains(&self, ptr: NonNull<u8>) -> bool
Whether ptr lies within [base, base + size).
Implemented as (p - base) < size using wrapping subtraction so the
check remains correct when the region’s end address wraps past
usize::MAX (rare on 64-bit, but possible on 16-/32-bit no_std
targets). A naive p >= base && p < base + size would compute an
end < base after wrap and report every pointer as out-of-range.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl FixedRange for HeapBytes
impl FixedRange for HugePageBacked
impl FixedRange for LockedMmapBacked
impl FixedRange for MmapBacked
impl<'a> FixedRange for StaticBacked<'a>
impl<B: FixedRange> FixedRange for BumpArena<B>
impl<B: FixedRange> FixedRange for StackAlloc<B>
impl<I: Allocator + FixedRange, const EPOCHS: usize> FixedRange for Quarantine<I, EPOCHS>
impl<I: Allocator + FixedRange> FixedRange for SplitMetadata<I>
impl<I: FixedRange, H: WatermarkHandler> FixedRange for Watermark<I, H>
target_has_atomic=ptr only.impl<I: FixedRange, P: AllocFaultPolicy> FixedRange for Faulty<I, P>
impl<I: FixedRange> FixedRange for CacheJitter<I>
FixedRange passthrough so this wrapper composes over a lazy_commit
MmapBacked and similar backings.
Footgun: the displacement header is written and MAC-verified only in
this wrapper’s allocate/deallocate. If you nest it as a backing under
an arena — BumpArena<CacheJitter<..>> — the arena carves directly from
base()/size() and never calls CacheJitter::allocate/deallocate, so
no displacement is applied and no header is ever checked while the type
name still advertises the jitter. Keep the hardening wrapper outermost
(wrapping the allocator), never as the FixedRange an arena consumes.
impl<I: FixedRange> FixedRange for Canary<I>
FixedRange passthrough so this wrapper composes over a lazy_commit
MmapBacked and similar backings.
Footgun: canary words are written and verified only in this wrapper’s
allocate/deallocate. If you nest it as a backing under an arena —
BumpArena<Canary<..>> — the arena carves directly from base()/size()
and never calls Canary::allocate/deallocate, so no canary is ever
placed or checked and the overflow detection silently does nothing while
the type name still advertises it. Keep the hardening wrapper outermost
(wrapping the allocator), never as the FixedRange an arena consumes.
impl<I: FixedRange> FixedRange for PoisonOnFree<I>
FixedRange passthrough so this wrapper composes over a lazy_commit
MmapBacked and similar backings.
Footgun: the poison-on-free scrub runs only in this wrapper’s
deallocate. If you nest it as a backing under an arena —
BumpArena<PoisonOnFree<..>> — the arena carves directly from
base()/size() and its own deallocate is a no-op, so the scrub never
runs. Keep the hardening wrapper outermost (wrapping the allocator),
never as the FixedRange an arena consumes.
impl<I: FixedRange> FixedRange for Statistics<I>
impl<I: FixedRange> FixedRange for ZeroizeOnFree<I>
FixedRange passthrough so this wrapper composes over a lazy_commit
MmapBacked and similar backings.
Footgun: the zeroize-on-free scrub runs only in this wrapper’s
deallocate. If you nest it as a backing under an arena —
BumpArena<ZeroizeOnFree<..>> — the arena carves directly from
base()/size() and its own deallocate is a no-op, so the scrub never
runs. Keep the hardening wrapper outermost (wrapping the allocator),
never as the FixedRange an arena consumes.