Text: bytes and code points

pub fn byte_at(self: text, i: integer) -> integer

Return the BYTE at position i (0 up to size()) as integer 0-255, or 0 for out-of-bounds; a negative i counts from the end, as a slice bound does (byte_at(-1) is the last byte). Unlike text[i] which decodes the UTF-8 codepoint containing byte i (walking back through continuation bytes), byte_at(i) is a pure O(1) byte read. Use in ASCII-heavy scanning hot paths (tokenisers, regex- like loops) where the UTF-8 decode is wasted work — every non-ASCII byte still returns a valid 0-255 number; the caller compares against ASCII constants so byte semantics suffice. ~5-10× faster than text[i] for pure-ASCII checks.

pub fn text_from_bytes(bytes: const vector<u8>) -> text

Build a text from the raw UTF-8 bytes of a vector<u8> — the inverse of byte_at. Use in binary decoders (CBOR text, HPKE byte composition) that assemble a byte buffer and need to turn it back into text. Bytes that are not valid UTF-8 yield the empty text (never a crash); validate first if you must tell "empty input" from "invalid bytes" apart.

pub fn text_from_byte_range(bytes: const vector<u8>, lo: integer, hi: integer) -> text

The same over the byte RANGE lo..hi of the buffer, read in place: what a decoder that has found a text's span writes instead of text_from_bytes(bytes[lo..hi]), whose slice is a fresh vector ((Slice-Value)) built to be read once. The bounds are the slice's (a negative one counts from the end; both clamp); a reversed or empty range, or invalid UTF-8, is "". Its own name, not an overload: a native is dispatched by name.

pub fn chr(cp: integer) -> text

Build a one-character text from a Unicode CODE POINT — the inverse of the ch as integer that text iteration already gives you, and the code-point twin of text_from_bytes' byte route. Use when you have a number and need the character it names: decoding an escape (\u{...}, an HTML entity), walking a code-point table, or reassembling text a code point at a time. chr(65) "A" chr(233) "é" chr(20013) "中" chr(128512) "😀" A code point that names no character answers the EMPTY text, never a crash: a surrogate (D800-DFFF), anything past U+10FFFF, a negative number — and also 0, because character uses 0 as its null and text iteration stops there, so a NUL built here could not be read back. If you need an embedded NUL, go through the byte route: text_from_bytes([0]) carries one.