Bytes

bytes is a sequence of bytes that holds any values, NUL and 0x80 to 0xFF included: the contents of a binary file, a network message, or an image. Like a string it never changes, and operations make new bytes. A literal is written b"..." with the escapes of strings, where \x00 is allowed too, and characters outside ASCII stand for their UTF-8 bytes:

bytes request = b"GET / HTTP/1.1\r\n"
bytes header = b"\x89PNG\r\n\x1a\n"
print(len(header), header[0], header)     // 8 137 b"\x89PNG\r\n\x1a\n"

b[i] is the byte at i, a u8, and for i, byte in b visits each one. slice(b, start, end) shares the bytes rather than copying them, so taking part of large data is cheap. b + c joins two, and += adds to a variable. == and != compare the values, as do < and the other orderings, byte by byte with a shorter sequence first when it starts the other. x in b asks whether b holds the byte x or, when x is bytes, that sequence. Bytes can be map keys, compared by their values, and match patterns:

match slice(request, 0, 4) do
    when b"GET " then
        print("a read")
    when b"POST", b"PUT " then
        print("a write")
    else
        print("something else")
end

These built-ins work on bytes; find, starts_with, ends_with, split, and replace are the ones for text, given bytes:

Built-in Result Behavior
find(b, part), find(b, part, start) i64 the index of the first part at or after start, or -1
find_last(b, part) i64 the index of the last part, or -1
count(b, part) i64 how many times part is in b, without overlaps
starts_with(b, part), ends_with(b, part) bool whether b starts or ends with part
split(b, separator) bytes[] the pieces between each separator, sharing b
replace(b, old, new) bytes b with every old replaced by new
to_bytes(text) bytes the bytes of a string's UTF-8, shared with it
from_utf8(b) Result[str] the text the bytes hold, or an error of kind "invalid_utf8" when they are not UTF-8 or hold a NUL
from_utf8_lossy(b) str the text, with U+FFFD for each byte that does not start valid UTF-8 and for each NUL
bytes_from(values) bytes bytes with the values of a u8[]
to_array(b) u8[] an array of the values
repeat_bytes(byte, count) bytes count times the byte, from 0 to 255
zero_bytes(count) bytes count zero bytes

print, to_str, and f-strings show bytes as a literal would write them: printable ASCII as it is, and \x.. escapes for the rest. Bytes and text are different types: one is never used for the other, and to_bytes and from_utf8 convert between them. An index outside the bytes, an empty separator for split, an empty old for replace, and a byte outside 0 to 255 for repeat_bytes are runtime errors.