Bytes Carries What Owns Its Memory; a ref Bytes That Is Only Read Takes Any Run of BytesStatus: Accepted
Date: October 19, 2026
Answers: #718,
a Mapped handed where a Bytes is taken, and the copy
#701 part 3 asks
about, a Vec[u8] that becomes a Bytes
Refines: ADR-283 D20 (a Bytes is one shared, immutable
buffer; building one is the one copy)
Related: ADR-016 D5 (Mapped derefs to Bytes), Part I
2.6, 6.6, Part III 17.2
fn lines(b: ref Bytes) -> i64 { … }
let m = fs::map("in.txt", fs::Root::Anywhere)
lines(m) // a mapping, read
http::Server(ROUTES; state: [m]) // a mapping, kept as a body
let b = Bytes(v) // a Vec[u8], handed over
Bytes is the language’s run of bytes that several holders share. ADR-016 D5
made a mapped file one, and Part III 17’s server answers with a mapped page as
a body that costs a count per request. A Bytes that is one heap buffer and
nothing else can hold neither, and turning a Vec[u8] into one copies every
byte.
bytes crate: one Bytes over a static buffer, a Vec handed
over without a copy, or any owner (Bytes::from_owner, a mapping among
them); a clone is a count.ByteBuffer, heap or MappedByteBuffer, one API.Memory<byte>, with a MemoryManager for memory it does not own.mmap, an allocator, a literal. A function
that reads takes []const u8 and accepts all of them; the program frees
each with the call that matches how it was made, and keeps it alive itself
as long as a slice into it is used.Bytes reads the same whatever owns its memory.A Bytes holds a run of bytes and a counted handle on what owns them: memory
it allocated, a Vec[u8] handed over, or a mapped file. Reading - b[i],
cuts, len, find, the word reads - is the same for each and costs the same:
where the bytes are and how many is in the value itself. Handing one on is a
count. The memory lives as long as any Bytes or view that needs it.
Bytes(v) takes a Vec[u8] over and copies nothing.A program builds a Bytes by calling the type with a Vec[u8], which it
hands over. The vector’s memory becomes the buffer. fs::read makes its
Bytes the same way.
Mapped is a Bytes, by reference and by value.Where a Bytes is taken - a ref Bytes parameter, a Bytes that is kept, a
body, a field, an element - a Mapped may be given. It is the mapping, at a
count; nothing is copied, and the file stays mapped while any holder lives.
ref Bytes that is only read takes any run of bytes.A parameter b: ref Bytes whose function only reads b (it does not keep
it, return it or hand it to something that keeps it) is lowered to a plain run
of bytes, the slice Zig would take. Any Bytes, a Mapped, and the bytes of
a text (s.bytes) reach it without touching a count. Where the function keeps
b, it takes the Bytes with its owner (D1).
Mapped turned into a Bytes by a copy: a whole file copied with
nothing written for it, against fs::map’s nothing is copied.Bytes stays one heap buffer and Vec[u8] → Bytes copies (ADR-283
D20 as it was): the copy is of every byte of every file fs::read reads.A Bytes value grows from a pointer and a length (16 bytes on a 64-bit
target) to a pointer, a length and a handle on the owner (about 32). D4 keeps
that off the common path: a function that only reads takes the 16-byte run.
What it costs a program that holds many small Bytes in a list is a
measurement owed before the type is changed.