Memory

Raw memory helpers, byte operations, and slice construction in std.mem.

std.mem is the raw memory helper module. It provides byte copy, move, set, compare, pointer search, address helpers, and slice construction over existing storage.

These helpers do not run constructors or destructors for the bytes they touch. Callers are responsible for pointer validity, byte counts, alignment, and storage lifetime. See Memory Model for the language ownership, borrowing, drop, and raw-pointer rules around these helpers.

Byte Operations

import std.mem;

fn main() {
    let bytes = [0 as u8, 0 as u8, 0 as u8];

    mem.set(bytes.ptr, 7 as u8, bytes.length);
    assert bytes[0] == 7 as u8;

    mem.zero(bytes.ptr, bytes.length);
    assert bytes[0] == 0 as u8;
    assert mem.find(bytes.ptr, 0 as u8, bytes.length) != null;
}

Use copy only for non-overlapping ranges. Use move when source and destination may overlap.

import std.mem;

fn raw_ptr<T>(value: const &T) -> *u8 {
    return mem.address_of<T>(value);
}

fn main() {
    let src: i32 = 1234;
    let dst: i32 = 0;

    mem.copy(raw_ptr(&dst), raw_ptr(&src), 4);
    assert dst == 1234;
    assert mem.compare(raw_ptr(&dst), raw_ptr(&src), 4) == 0;
}

Slices From Pointers

mem.slice_of<T>(ptr, len) creates a non-owned [T] slice over existing storage. The slice does not extend the lifetime of that storage; keep the backing allocation, stack array, or owner alive while the slice is used.

import std.mem;

fn main() {
    let values: [i32, 3] = [4, 5, 6];
    let view = mem.slice_of<i32>(values.ptr, values.length);

    assert view.length == 3;
    assert view[2] == 6;
    assert !mem.is_owned<i32>(view);
}

mem.owned_slice<T>(ptr, len) marks a slice as owning the backing allocation. Only use it for allocation-backed memory that should be freed when the slice is dropped. Do not wrap stack arrays or borrowed storage with owned_slice.

Element Slots

std.mem also exposes low-level helpers for moving values into and out of typed storage slots:

import std.mem;

fn main() {
    let value = 10;
    let slot: *i32 = &value as *i32;

    mem.write_at<i32>(slot, 42);
    assert value == 42;

    let moved = mem.read_at<i32>(slot);
    assert moved == 42;
}

These helpers are meant for containers and manual slot management:

FunctionPurpose
write_at<T>(dst, value)Move/write a value into a typed slot.
read_at<T>(src) -> TMove/read a value out of a typed slot.
move_at<T>(dst, src)Move one typed slot into another.
drop_at<T>(ptr)Drop the value at a typed slot.

Prefer collection APIs in ordinary code. Incorrect slot use can duplicate, leak, or prematurely drop owned values.

For the language-level cleanup rules behind drop_at, see RAII and Drop.

API Reference

FunctionPurpose
copy(dst, src, n)Copy bytes without overlap.
move(dst, src, n)Copy bytes with overlap support.
set(dst, value, n)Fill bytes.
zero(ptr, n)Fill bytes with zero.
compare(a, b, n)Compare byte ranges.
find(ptr, byte, n)Find a byte.
slice_of<T>(ptr, len)Create a non-owned slice.
owned_slice<T>(ptr, len)Create an owned slice.
is_owned<T>(slice)Query slice ownership.
write_at<T>(dst, value)Move/write a value into a typed slot.
read_at<T>(src)Move/read a value out of a typed slot.
move_at<T>(dst, src)Move one typed slot into another.
drop_at<T>(ptr)Drop a value at a typed slot.
str_from_raw(ptr)Convert a null-terminated raw pointer to str.
address_of(...)Get raw byte pointers for strings or references.
swap(a, b, n)Swap byte ranges.