Core

std.mem

Span metadata, copy and equality helpers, and the allocator surface.

When To Use std.mem

In Zerolang, use std.mem for spans, clamped span views, copy/fill, fixed-buffer allocators, explicit byte buffers, and memory-budget-visible collection foundations.

Runnable today:

The item-generic helpers currently support these direct-backed scalar element types: Bool, u8, u16, usize, i32, u32, i64, and u64.

APIReturnNotes
std.mem.copy(dst, src)usizeCopies from Span<u8> into caller-owned MutSpan<u8> storage and returns the copied byte count.
std.mem.copyItems(dst, src)usizeCopies matching scalar Span<T> items into caller-owned mutable item storage and returns the copied item count.
std.mem.fill(dst, value)usizeFills caller-owned MutSpan<u8> storage with a u8 byte and returns the filled byte count.
std.mem.fillItems(dst, value)usizeFills caller-owned mutable scalar item storage with a matching T value and returns the filled item count.
std.mem.eql(a, b)BoolCompares string-backed byte inputs.
std.mem.span(value)Span<u8>Builds a native Span<u8> view over a string literal.
std.mem.contains(items, needle)BoolSearches readable contiguous non-owned scalar T storage for a matching value.
std.mem.compareI32(left, right)i32Lexicographically compares two Span<i32> values and returns -1, 0, or 1.
std.mem.compareU8(left, right)i32Lexicographically compares two Span<u8> values and returns -1, 0, or 1.
std.mem.compareBytes(left, right)i32Alias-style byte lexicographic comparison for Span<u8> values.
std.mem.compareU32(left, right)i32Lexicographically compares two Span<u32> values and returns -1, 0, or 1.
std.mem.compareUsize(left, right)i32Lexicographically compares two Span<usize> values and returns -1, 0, or 1.
std.mem.startsWith(items, prefix)BoolChecks whether a scalar span begins with a matching prefix span.
std.mem.endsWith(items, suffix)BoolChecks whether a scalar span ends with a matching suffix span.
std.mem.splitBefore(items, delimiter)Span<T>Returns the read-only scalar item prefix before the first delimiter, or the full span when absent.
std.mem.splitAfter(items, delimiter)Span<T>Returns the read-only scalar item suffix after the first delimiter, or an empty span when absent.
std.mem.isEmpty(items)BoolReports whether readable contiguous scalar item storage has zero items.
std.mem.chunkCount(items, chunkSize)usizeReturns the number of non-overlapping chunks needed to cover the span, or 0 when chunkSize is zero.
std.mem.chunk(items, chunkIndex, chunkSize)Span<T>Returns a clamped read-only scalar item chunk by zero-based chunk index.
std.mem.windowCount(items, windowSize)usizeReturns the number of overlapping fixed-size windows available in a span, or 0 when the size is zero or larger than the span.
std.mem.window(items, windowIndex, windowSize)Span<T>Returns an overlapping read-only scalar item window by zero-based window index.
std.mem.advance(items, cursor, count)usizeReturns a clamped cursor advanced by at most count items.
std.mem.cursorDone(items, cursor)BoolReports whether a cursor is at or past the end of a span.
std.mem.remaining(items, cursor)Span<T>Returns the clamped read-only scalar item view from cursor to the end.
std.mem.cursorChunk(items, cursor, count)Span<T>Returns a clamped read-only scalar item window beginning at cursor.
std.mem.prefix(items, count)Span<T>Returns a clamped read-only scalar item prefix view.
std.mem.dropPrefix(items, count)Span<T>Returns a clamped read-only scalar item view after the first count items.
std.mem.suffix(items, count)Span<T>Returns a clamped read-only scalar item suffix view.
std.mem.dropSuffix(items, count)Span<T>Returns a clamped read-only scalar item view before the last count items.
std.mem.slice(items, start, count)Span<T>Returns a clamped read-only scalar item window beginning at start.
std.mem.len(bytes)usizeReturns the length of a fixed array, Span<T>, or MutSpan<T>.
std.mem.get(bytes, index)Maybe<T>Reads one indexed element from an array/span-like value when the index is in bounds.
std.mem.eqlBytes(a, b)BoolCompares two Span<T>/MutSpan<T> values with the same element type.
std.mem.nullAlloc()NullAllocCreates an allocator that always returns null, useful for proving code does not allocate.
std.mem.fixedBufAlloc(buffer)FixedBufAllocCreates a mutable fixed-buffer allocator from caller-owned MutSpan<u8> bytes.
std.mem.arena(buffer)FixedBufAllocArena-style alias over the fixed-buffer allocator model; reset rewinds the caller-owned storage.
std.mem.pageAlloc()PageAllocExplicit host allocator handle metadata; it never creates an ambient global allocator.
std.mem.generalAlloc()GeneralAllocExplicit general allocator handle metadata; callers still pass allocator state deliberately.
std.mem.allocBytes(alloc, len)Maybe<MutSpan<u8>>Allocates bytes from NullAlloc or a mutable FixedBufAlloc binding.
std.mem.byteBuf(alloc, len)Maybe<owned<ByteBuf>>Creates an owned byte buffer backed by explicit caller-provided allocator storage.
std.mem.bufBytes(&buf)MutSpan<u8>Borrows writable bytes from an owned ByteBuf.
std.mem.bufLen(&buf)usizeReturns the live length of a ByteBuf.
std.mem.reset(&mut arena)VoidResets caller-owned arena/fixed-buffer allocation state.
std.mem.capacity(arena)usizeReports fixed-buffer capacity.
std.mem.vec(storage)VecMonomorphic byte vector over caller-owned mutable storage.
std.mem.vecPush(&mut vec, value)BoolAppends one byte when capacity remains; returns false instead of growing implicitly.
std.mem.vecBytes(&vec)Span<u8>Borrows the live bytes in the vector without copying.
std.mem.vecGet(&vec, index)Maybe<u8>Reads one live vector byte when index is in bounds.
std.mem.vecSet(&mut vec, index, value)BoolReplaces one live vector byte when index is in bounds; returns false out of bounds.
std.mem.vecClear(&mut vec)usizeResets live length to zero and keeps caller-owned storage available for reuse.
std.mem.vecPop(&mut vec)BoolRemoves one live byte when the vector is non-empty.
std.mem.vecTruncate(&mut vec, len)usizeShrinks the live length to at most len and returns the resulting length.
std.mem.vecRemoveSwap(&mut vec, index)BoolRemoves one live byte by replacing it with the last live byte. Returns false out of bounds.
std.mem.vecIndex(&vec, value)usizeReturns the first live index for value, or the current live length when absent.
std.mem.vecContains(&vec, value)BoolReports whether a byte value is present in the live vector prefix.
std.mem.vecInsertUnique(&mut vec, value)BoolAppends value only when it is absent and capacity remains.
std.mem.vecRemoveValue(&mut vec, value)BoolSwap-removes the first matching live byte by value.
std.mem.vecLen(&vec)usizeReports current vector length.
std.mem.vecCapacity(&vec)usizeReports caller-provided vector capacity.
std.mem.vecRemaining(&vec)usizeReports remaining byte-vector capacity. Returns 0 when the vector is full.
std.mem.vecIsEmpty(&vec)BoolReports whether the vector has no live bytes.
std.mem.vecIsFull(&vec)BoolReports whether the vector has no remaining capacity.

Example

type SliceView {    bytes: Span<u8>,    values: Span<i32>,} pub fn main(world: World) -> Void raises {    let bytes: Span<u8> = std.mem.span("zero-memory")    let same: Span<u8> = std.mem.span("zero-memory")    var scratch: [11]u8 = [0_u8; 11]    let copied: usize = std.mem.copy(scratch, bytes)    var ints: [3]i32 = [1, 2, 3]    let intSpan: MutSpan<i32> = ints    let filled: usize = std.mem.fillItems(intSpan, 7)    let prefix: Span<i32> = std.mem.prefix(intSpan, 2)    let suffix: Span<i32> = std.mem.suffix(intSpan, 2)    let middle: Span<i32> = std.mem.slice(intSpan, 1, 1)    let before: Span<i32> = std.mem.splitBefore(intSpan, 7)    let after: Span<i32> = std.mem.splitAfter(intSpan, 7)    let chunk: Span<i32> = std.mem.chunk(intSpan, 1_usize, 2_usize)    let sliding: Span<i32> = std.mem.window(intSpan, 1_usize, 2_usize)    let cursor: usize = std.mem.advance(intSpan, 0_usize, 2_usize)    let rest: Span<i32> = std.mem.remaining(intSpan, cursor)    let view: SliceView = SliceView { bytes: bytes, values: intSpan }    let ordered: Bool = std.mem.compareI32(prefix, suffix) == 0    let starts: Bool = std.mem.startsWith(view.bytes, std.mem.span("zero"))    let ends: Bool = std.mem.endsWith(view.bytes, std.mem.span("memory"))    if copied == 11 && filled == 3 && ordered && starts && ends && std.mem.len(view.bytes) == 11 && std.mem.eqlBytes(view.bytes, same) && std.mem.len(view.values) == 3 && std.mem.contains(view.values, 7) && std.mem.isEmpty(before) && std.mem.len(after) == 2 && std.mem.len(prefix) == 2 && std.mem.len(suffix) == 2 && std.mem.len(middle) == 1 && std.mem.len(chunk) == 1 && std.mem.len(sliding) == 2 && std.mem.len(rest) == 1 && !std.mem.cursorDone(intSpan, cursor) {        check world.out.write("memory type forms runnable\n")    }}

Allocator Example

pub fn main(world: World) -> Void raises {    var storage: [8]u8 = [0, 0, 0, 0, 0, 0, 0, 0]    var alloc: FixedBufAlloc = std.mem.fixedBufAlloc(storage)    let bytes: Maybe<MutSpan<u8>> = std.mem.allocBytes(alloc, 4)    if bytes.has {        bytes.value[0] = 90        check world.out.write("fixed buffer allocated\n")    }}

Effects: none beyond writes performed by caller code.

Allocation behavior:

  • NullAlloc always returns null.
  • FixedBufAlloc and Arena return MutSpan<u8> views into caller-owned storage.
  • ByteBuf owns a slice of explicit allocator storage and never reaches for a global heap.

Use std.mem.allocBytes(alloc, capacity) when a byte-oriented API needs allocator-backed mutable storage directly. std.collections.fixedSet, std.collections.fixedDeque, and std.collections.fixedMap can use those returned spans as caller-owned backing storage.

Ownership: returned spans borrow from the original fixed buffer; no heap ownership is created.

Target support: current compiler targets. Direct native builds lower FixedBufAlloc locals only; PageAlloc, GeneralAlloc, and NullAlloc locals type-check but fail zero build with a BLD004 diagnostic that points back to std.mem.fixedBufAlloc.

Reporting Contract

zero mem --json [graph-input] reports the allocator contract in machine-readable form:

  • memoryBudgets: stack, static, heap, arena, fixed-buffer, collection-capacity, allocator-capacity, requested-allocation, and linear-memory floor budgets.
  • allocatorFacts: NullAlloc, FixedBufAlloc, Arena, PageAlloc, and GeneralAlloc usage, capacity, failure behavior, and hidden-global-allocator status.
  • allocationInstrumentation: pay-as-used hooks for attempts, successes, failures, requested bytes, granted bytes, and peak live bytes.
  • collectionFacts: fixed-capacity Vec, fixed-storage std.collections helpers, and owned ByteBuf, including growth/failure/cleanup behavior.
  • safetyFacts: the selected profile plus the current bounds, initialization, aliasing, lifetime, ownership, span, MIR, literal integer range-check, runtime arithmetic, and unchecked-surface facts.

All heap budgets are explicit. A program that only uses std.mem remains at heapBytes: 0, globalHeapBytes: 0, and hiddenHeapAllocation: false unless an allocator API documents otherwise.

Design Notes

No standard collection may silently allocate from a global heap. Heap-owning APIs will require an allocator capability and document ownership, capacity, and cleanup.