March Docs

Bytes

Bytes module: raw byte manipulation.

Bytes wraps a String, which in the runtime is an array-backed buffer: march_string is {rc, tag, pad, len, data[]} — one allocation, an explicit length field, and a contiguous NUL-safe payload. Nothing here treats a String as text: string_byte_at, string_slice, string_chars and char_from_int are all byte-indexed in both backends.

This replaced Bytes(List(Int)), which cost one ~32-byte cons cell per byte and made length O(n), get O(i) and slice O(start+len). Measured on a 64 000-byte payload (interpreted): length 544 ms/call, get(last)

  1. See specs/plans/2026-08-10-array-backed-bytes-design.md.

The wrapper constructor is deliberately kept (a Bytes value is still a one-field boxed ADT cell with its payload at offset 16), because lib/tir/repr.ml, llvm_case.ml and drop.ml all encode assumptions about that shape, and because the C runtime builds these cells by hand.

to_list/from_list were O(1) under the old representation and are O(n) now. That is the one regression; see the design doc's audit of the callers.

This module is self-contained: it does not depend on List. or String. being loaded, so it can be tested or used in isolation.

Types

typeBytesBytes = Bytes(String)#

Functions

fnconcatconcat(b1, b2)#

Concatenate two Bytes values. O(n).

fndecode_base64decode_base64(s)#

Decode a Base64 string to Bytes. Returns Err on invalid input.

fndecode_utf8decode_utf8(b) do Ok(to_string(b)) end#

Decode UTF-8 bytes to a String. Returns Ok(s) always (same as to_string).

fnemptyempty() do Bytes("") end#

An empty Bytes value.

fnencode_base64encode_base64(b)#

Encode Bytes as a Base64 string (with padding).

fnencode_utf8encode_utf8(s) do from_string(s) end#

Encode a String as UTF-8 bytes. Equivalent to from_string for March strings.

fnfrom_hexfrom_hex(s)#

Parse a hex string to Bytes. Returns Err if the input is not valid hex.

fnfrom_listfrom_list(xs)#

Wrap a List(Int) of byte values (0–255) as Bytes. O(n).

fnfrom_stringfrom_string(s) do Bytes(s) end#

Convert a String to Bytes (raw UTF-8 byte values, each 0–255). O(1).

fnfrom_u8_arrfrom_u8_arr(a) do u8_arr_to_bytes(a) end#

Copy [a]'s bytes into a fresh immutable Bytes. O(n) copy.

fngetget(b, i)#

Byte at position i (0-based). Panics if out of bounds. O(1).

fnis_emptyis_empty(b)#

True if the Bytes is empty. O(1).

fnlengthlength(b)#

Number of bytes. O(1).

fnsliceslice(b, start, len)#

Sub-slice: bytes from position start with given length. O(len).

fnto_hexto_hex(b)#

Encode Bytes as a lowercase hexadecimal string.

fnto_listto_list(b)#

Unwrap Bytes to a List(Int). O(n).

fnto_stringto_string(b)#

Convert Bytes back to a String (bytes interpreted as UTF-8). O(1).

fnto_u8_arrto_u8_arr(b) do bytes_to_u8_arr(b) end#

Copy [b]'s bytes into a fresh NativeU8Arr for SIMD/numeric work. O(n) copy — the layouts cannot be shared.