Skip to content

Bytes

Build and borrow binary buffers with explicit UTF-8 conversion.

Updated View as Markdown

The current prelude represents byte data with ordinary sequence types:

  • []byte is an owned growable List[byte];
  • [..]byte is a borrowed Slice[byte];
  • Bytes is the read-only byte protocol;
  • Buffer extends it with builder operations.

There is no installed nominal bytes or Buffer struct from the old design.

Owned buffers

mut output: []byte = List.with_capacity[byte](128)
output.append(65u8)
output.append(66u8)

A byte list supports normal list operations plus the Buffer contract: append, clear, append_int, append_float, append_all, and append_string.

mut output: []byte = []
output.append_string("count=")
output.append_int(42)

Builder methods update the mutable receiver and grow its backing storage as needed. clear() resets the length to zero but keeps capacity for reuse. append_int and append_float write decimal ASCII directly into reserved storage without allocating an intermediate string.

append_all accepts any value implementing Bytes, so an owned buffer can copy from either another list or a borrowed slice:

mut packet: []byte = []
packet.append_all(header.bytes())
packet.append_all(payload)

Borrowed views

Use a slice when a callee only needs to read:

fn checksum(data: [..]byte): int {
    return fold_checksum(data)
}

Slices can be created from list ranges and passed to file or socket writes without copying:

match packet.slice(4..packet.len()) {
    Some(payload) => send(payload)
    None => report_short_packet()
}

A slice borrows the parent allocation. It cannot grow and does not implement Buffer. Keep the parent alive and do not retain the raw pointer across a mutation that can reallocate its storage.

Bytes protocol

Any Bytes value exposes:

Method Meaning
byte_len() Encoded length
byte_ptr() Arena-relative pointer to first byte
byte_is_empty() Whether length is zero
byte_at(index) Safe optional lookup
is_valid_utf8() Strict UTF-8 validation
decode_utf8() Optional decoded string

byte_at rejects negative and out-of-range indexes with None. byte_ptr() is an arena-relative low-level pointer intended for the prelude and host wrappers. Do not retain it across buffer mutation, scope exit, or suspension unless the low-level contract explicitly pins the allocation.

Text conversion

Text and bytes are never conflated:

owned: []byte = text.to_bytes()
borrowed: [..]byte = text.bytes()
decoded: string? = owned.decode_utf8()

decode_utf8 performs strict Unicode validation and copies valid data into a fresh string. It rejects overlong encodings, surrogate code points, truncated sequences, stray continuation bytes, and values above U+10FFFF.

string.bytes() borrows the string’s storage. string.to_bytes() and decode_utf8() allocate owned results. Choose based on whether ownership must cross the current scope or asynchronous boundary.

Protocols with replacement semantics should implement that policy explicitly instead of assuming the standard decoder is lossy.

Empty values

Empty byte lists and slices report a length of zero. Their pointer value is an implementation detail and may be null-like; callers must never dereference byte_ptr() when byte_len() is zero. The safe protocol methods already enforce that rule.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close