Standard Library — Types
Contents
Built-in Enums
The following enum types are defined by the prelude and are always available. A small set of variant constructors (Some, None, Ok, Err, Yielded, Done) are also available without qualification. All other prelude enum variants require qualification (e.g. Ordering.Less, IoError.Eof).
Ordering
enum Ordering
Less
Equal
Greater
end
Represents the result of a comparison. Returned by the compare method of the Comparable[T] interface (see stdlib/interfaces.md). Ordering is a simple enum with no associated data.
Constructing:
result = 3.compare(5) # Ordering.Less
result = 5.compare(5) # Ordering.Equal
result = 7.compare(5) # Ordering.Greater
Pattern matching:
match a.compare(b)
Ordering.Less then println("a < b")
Ordering.Equal then println("a == b")
Ordering.Greater then println("a > b")
end
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[Ordering] |
always (built-in enum equality) |
Eq[Ordering] |
always (built-in enum equality) |
Hash |
always (no associated data) |
ToString |
always (enum auto-conformance) |
Option[T]
enum Option[out T]
Some(T)
None
end
Represents an optional value. The ? suffix is syntactic sugar: int? means Option[int].
Constructing:
x: int? = Some(42)
y: int? = None
Destructuring:
match x
Some(value) then println("got: {value}")
None then println("nothing")
end
if x matches Some(value)
println("got: {value}")
end
Propagation with ?: The ? operator unwraps Some(v) to v, or immediately returns None from the enclosing function. The enclosing function must return Option[U] for some U. See lang/semantics/values.md §2.12.3.
fn firstWord(text: str?) -> str?
value = text? # unwrap or return None
return Some(value.split(" ")[0])
end
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[Option[T]] |
when T: PartialEq[T] |
Eq[Option[T]] |
when T: Eq[T] |
Hash |
when T: Hash |
ToString |
when T: ToString |
Result[T, E]
enum Result[out T, out E]
Ok(T)
Err(E)
end
Represents success or failure. Replaces exceptions for error handling.
Constructing:
success: Result[int, str] = Ok(42)
failure: Result[int, str] = Err("parse error")
result = int.parse("42") # Ok(42)
result = int.parse("nope") # Err("invalid character: n")
Destructuring:
match result
Ok(value) then println("got: {value}")
Err(e) then println("error: {e}")
end
Propagation with ?: The ? operator unwraps Ok(v) to v, or immediately returns Err(e) from the enclosing function. The enclosing function must return Result[U, E] where E matches the error type. See lang/semantics/values.md §2.12.3.
fn loadAndParse(path: str) -> Result[int, str]
content = readFile(path)? # unwrap Ok or return Err
value = int.parse(content)? # chain multiple fallible calls
return Ok(value)
end
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[Result[T, E]] |
when T: PartialEq[T] and E: PartialEq[E] |
Eq[Result[T, E]] |
when T: Eq[T] and E: Eq[E] |
Hash |
when T: Hash and E: Hash |
ToString |
when T: ToString and E: ToString |
GeneratorResult[Y, R]
enum GeneratorResult[out Y, out R]
Yielded(Y)
Done(R)
end
Returned by Generator[Y, R, N].next(). See lang/types.md §3.3.
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[GeneratorResult[Y, R]] |
when Y: PartialEq[Y] and R: PartialEq[R] |
Eq[GeneratorResult[Y, R]] |
when Y: Eq[Y] and R: Eq[R] |
Hash |
when Y: Hash and R: Hash |
ToString |
when Y: ToString and R: ToString |
IoError
enum IoError
Eof
Other(str)
end
Represents I/O errors. Used by readln (in stdlib/functions.md) and the io module file functions (stdlib/io.md).
Variants:
Eof— End-of-file reached (no more input available)Other(str)— Other I/O error with a descriptive message
Constructing:
err1 = IoError.Eof
err2 = IoError.Other("stdin closed")
Pattern matching:
match readln()
Ok(line) then println("got: {line}")
Err(IoError.Eof) then println("end of input")
Err(IoError.Other(msg)) then println("I/O error: {msg}")
end
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[IoError] |
always (built-in enum equality) |
Eq[IoError] |
always (built-in enum equality) |
Hash |
always (str is hashable) |
ToString |
always (enum auto-conformance) |
Generator[Y, R, N]
Generator[Y, R=(), N=never]
A built-in opaque type representing a suspended generator. Created by calling a gen fn function. Generator is not a struct or enum — it is a compiler-managed type with no user-accessible variants or fields.
Type parameters:
Y— the yield type: values produced viayieldR— the return type: the value produced viareturn(default:())N— the next type: values the caller passes via.next(Some(value))(default:never)
Common forms (via default type parameters):
Generator[int]— simple iterator, equivalent toGenerator[int, (), never]Generator[int, str]— iterator with return value, equivalent toGenerator[int, str, never]Generator[int, str, float]— full two-way communication
Methods:
fn next(mut self, value: Option[N]) -> GeneratorResult[Y, R]— resume the generator, optionally passing a value. WhenN = never,Option[never]can only beNone, so callers may writegen.next(None)(the compiler elides the argument since noSome(never)value is constructible).
Interface conformance:
| Interface | Condition |
|---|---|
Iterator[Y] |
when R = () and N = never |
Iterable[Y] |
when R = () and N = never (returns self) |
For full generator semantics, see lang/types.md §3.3.
Tuples
Tuple[out T1, out T2, ..., out Tn] is a built-in, fixed-size, heterogeneous, immutable type with 2 to 10 type parameters. All type parameters are covariant — tuples have no mutation methods, so covariance is sound. Tuples are part of the prelude and available without import.
Type syntax:
Tuple[int, str] # 2-tuple
Tuple[int, str, bool] # 3-tuple
Literal syntax:
pair = (1, "hello") # Tuple[int, str]
triple = (true, 3.14, "yes") # Tuple[bool, float, str]
Element access:
pair.0 # first element
pair.1 # second element
The index must be a compile-time integer literal within the tuple's arity.
Destructuring:
(x, y) = (10, 20)
(a, b, c) = triple
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[Tuple[...]] |
when all element types satisfy PartialEq |
Eq[Tuple[...]] |
when all element types satisfy Eq |
Hash |
when all element types satisfy Hash |
ToString |
when all element types satisfy ToString |
Tuples do not satisfy Comparable or Iterable.
Built-in Collections
List[T]
An ordered, growable sequence of elements.
Construction:
items = [1, 2, 3, 4, 5] # List[int]
names = ["alice", "bob"] # List[str]
empty = [] # List[never] — assignable to any List[T]
typed: List[int] = [] # explicit annotation required to mutate later
Bracket access:
first = items[0] # int — returns the element
items[0] = 10 # sets the element (requires mut)
Out-of-bounds access is a runtime error (panics). The index must be of type uint; only indices less than the list length are valid.
Methods:
| Signature | Description |
|---|---|
fn length(self) -> uint |
Number of elements. |
fn isEmpty(self) -> bool |
true if length is 0. |
fn get(self, index: uint) -> Option[T] |
Return the element at index, or None if out of bounds. |
fn push(mut self, value: T) |
Append an element to the end. |
fn pop(mut self) -> Option[T] |
Remove and return the last element, or None if empty. |
fn insert(mut self, index: uint, value: T) |
Insert at index, shifting subsequent elements right. Panics if index > length. |
fn remove(mut self, index: uint) -> T |
Remove and return the element at index, shifting subsequent elements left. Panics if out of bounds. |
fn first(self) -> Option[T] |
Return the first element, or None if empty. |
fn last(self) -> Option[T] |
Return the last element, or None if empty. |
fn contains(self, value: T) -> bool |
true if any element equals value. Requires T: PartialEq[T]. |
fn indexOf(self, value: T) -> Option[uint] |
Index of the first occurrence, or None. Requires T: PartialEq[T]. |
fn concat(self, other: List[T]) -> List[T] |
Return a new list with all elements of self followed by all elements of other. |
fn reverse(self) -> List[T] |
Return a new list with elements in reverse order. |
fn sort(self) -> List[T] |
Return a new sorted list. Requires T: Comparable[T]. Stable sort — preserves the relative order of elements that compare equal. |
fn clear(mut self) |
Remove all elements, leaving the list empty. |
List[T] also inherits the following methods from Iterable[T] (stdlib/interfaces.md): map, flatMap, filter, reduce, find, any, all, join, each, enumerate. The map, filter, flatMap, and enumerate methods return lazy Iterator values; use toList(), toMap(), or toSet() to materialize.
Concatenation:
combined = [1, 2].concat([3, 4]) # [1, 2, 3, 4]
List concatenation is an explicit method call. The + operator is not overloaded for lists — + works only on numeric types and str.
Iteration:
for item in items
println("{item}")
end
for (i, item) in items.enumerate()
println("{i}: {item}")
end
enumerate() is inherited from Iterable[T] (stdlib/interfaces.md) and returns Iterator[Tuple[uint, T]]. Tuple destructuring in the for loop binds the index and element.
The for loop calls iter(), which returns an Iterator[T]. Each element has type T.
Structurally modifying a list (e.g., push, pop, insert, remove) during iteration is a runtime panic. Element-level mutation via bracket assignment is safe (see types.md §3.4).
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[List[T]] |
when T: PartialEq[T] — element-wise equality, same length |
Eq[List[T]] |
when T: Eq[T] |
Iterable[T] |
always — iter() iterates over elements |
ToString |
when T: ToString — output format is implementation-defined and intended for diagnostic purposes only, not for serialization or user-facing display |
Map[K, V]
A hash map from keys to values.
Key constraint: K must satisfy both Eq[K] and Hash. This is enforced at every point where Map[K, V] is written in a type expression. Type parameters used as map keys must declare the required constraints in their bounds. The compiler checks constraint satisfaction at declaration sites, not usage sites. The Eq requirement (rather than PartialEq) guarantees reflexive equality — a key always equals itself, which is necessary for reliable lookup and membership testing:
Map[str, int] # ok — str implements Eq and Hash
Map[Point, str] # ok — if Point implements Eq and Hash
Map[float, str] # error — float does not implement Eq (NaN violates reflexivity)
Map[List[int], str] # error — List does not implement Hash
Construction:
m = {a: 1, b: 2, c: 3} # Map[str, int]
empty = {} # Map[never, never] — assignable to any Map[K, V]
typed: Map[str, int] = {} # explicit annotation also valid
Bare identifiers in map literals are always string keys. Empty strings are valid keys:
{"": 0} # Map[str, int] with empty string as key
Computed keys use bracket syntax:
{[42]: "hello"} # Map[int, str]
{[point]: "origin"} # Map[Point, str] — if Point: Eq[Point] & Hash
Bracket access:
val = m["a"] # int — returns the value, panics if key missing
m["c"] = 3 # sets the value (requires mut)
Map read access returns V directly. If the key is not present, it is a runtime error (panics). Use the .get() method for safe access that returns Option[V].
Methods:
| Signature | Description |
|---|---|
fn length(self) -> uint |
Number of key-value entries. |
fn isEmpty(self) -> bool |
true if length is 0. |
fn has(self, key: K) -> bool |
true if the key exists. |
fn get(self, key: K) -> Option[V] |
Return the value for key, or None if absent. Safe alternative to bracket access. |
fn set(mut self, key: K, value: V) |
Insert or update the entry for key. Functionally equivalent to bracket assignment outside of iteration. During iteration, set is always a structural modification (panic) because the runtime cannot distinguish insert-vs-update without a key lookup — use bracket assignment m[key] = value to safely update existing keys during iteration. |
fn delete(mut self, key: K) -> Option[V] |
Remove the entry for key and return the old value, or None if absent. |
fn keys(self) -> List[K] |
Return a list of all keys. Order is not guaranteed. |
fn values(self) -> List[V] |
Return a list of all values. Order matches keys(). |
fn entries(self) -> List[Tuple[K, V]] |
Return a list of key-value pairs as tuples. |
fn mapValues[U](self, f: fn(V) -> U) -> Map[K, U] |
Return a new map with f applied to each value. |
fn merge(self, other: Map[K, V]) -> Map[K, V] |
Return a new map containing all entries from both. If a key appears in both, other's value wins. |
fn clear(mut self) |
Remove all entries, leaving the map empty. |
Map[K, V] also inherits methods from Iterable[Tuple[K, V]] (stdlib/interfaces.md): map, flatMap, filter, reduce, find, any, all, join, each, enumerate. For these methods, the element type is Tuple[K, V]. The map, filter, flatMap, and enumerate methods return lazy Iterator values; use toList(), toMap(), or toSet() to materialize.
Iteration:
Maps iterate over key-value pairs as Tuple[K, V]:
Iteration order is unspecified. Programs must not depend on any particular order. Implementations are free to use insertion order, arbitrary order, or any other strategy.
for entry in m # entry: Tuple[str, int]
println("{entry.0} = {entry.1}")
end
for (k, v) in m # destructured: k: str, v: int
println("{k} = {v}")
end
for (_, v) in m # discard the key, bind only the value
println("{v}")
end
The single-variable form binds each Tuple[K, V] directly. The tuple destructuring form (k, v) destructures each pair into its elements. The _ placeholder discards a binding (see lang/semantics/patterns.md §2.14).
Structurally modifying a map (e.g., set, delete, bracket insertion of new keys) during iteration is a runtime panic. Updating an existing key's value via bracket assignment is safe (see types.md §3.4).
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[Map[K, V]] |
when K: PartialEq[K] and V: PartialEq[V] — same keys with equal values |
Eq[Map[K, V]] |
when K: Eq[K] and V: Eq[V] |
Iterable[Tuple[K, V]] |
always — iter() iterates over key-value pairs |
ToString |
when K: ToString and V: ToString — output format is implementation-defined and intended for diagnostic purposes only, not for serialization or user-facing display |
Set[T]
An unordered collection of unique values.
Key constraint: T must satisfy both Eq[T] and Hash. This is enforced at every point where Set[T] is written in a type expression. Note that Set requires Eq[T] (not just PartialEq[T]) because set membership relies on reflexive equality — an element must equal itself for membership tests to be consistent.
Construction:
There is no literal syntax for Set. Use the static from method:
s = Set.from([1, 2, 3, 2, 1]) # Set[int] — duplicates discarded
names = Set.from(["alice", "bob"]) # Set[str]
typed: Set[str] = Set.from([]) # explicit annotation required for empty set
Methods:
| Signature | Description |
|---|---|
fn from(items: List[T]) -> Set[T] |
Static constructor. Duplicate elements in items are silently discarded. |
fn length(self) -> uint |
Number of elements. |
fn isEmpty(self) -> bool |
true if length is 0. |
fn contains(self, value: T) -> bool |
true if value is a member of the set. |
fn add(mut self, value: T) |
Add value to the set. No-op if already present. |
fn remove(mut self, value: T) -> bool |
Remove value from the set. Returns true if the element was present, false if not. |
fn union(self, other: Set[T]) -> Set[T] |
Return a new set containing all elements that appear in either set. |
fn intersection(self, other: Set[T]) -> Set[T] |
Return a new set containing only elements that appear in both sets. |
fn difference(self, other: Set[T]) -> Set[T] |
Return a new set containing elements in self that are not in other. |
fn clear(mut self) |
Remove all elements, leaving the set empty. |
Set[T] also inherits methods from Iterable[T] (stdlib/interfaces.md): map, flatMap, filter, reduce, find, any, all, join, each, enumerate. The map, filter, flatMap, and enumerate methods return lazy Iterator values; use toList(), toMap(), or toSet() to materialize.
Iteration:
Set[T] satisfies Iterable[T]. Iteration order is unspecified — programs must not depend on any particular order:
s = Set.from([3, 1, 2])
for item in s
println("{item}") # printed in unspecified order
end
Calling add, remove, or clear during iteration is a runtime panic.
Equality:
Two sets are equal if and only if they contain exactly the same elements (order is irrelevant):
Set.from([1, 2, 3]) == Set.from([3, 1, 2]) # true
Set.from([1, 2]) == Set.from([1, 2, 3]) # false
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[Set[T]] |
always (T: Eq[T] & Hash is already required by Set) |
Eq[Set[T]] |
always |
Iterable[T] |
always — iter() iterates over elements |
ToString |
when T: ToString — output format is implementation-defined and intended for diagnostic purposes only, not for serialization or user-facing display |
Buffer
A mutable, growable sequence of raw bytes. Unlike str (which is immutable and always valid UTF-8) and List[byte] (which is a generic collection), Buffer is purpose-built for binary data manipulation — encoding, decoding, and binary file I/O.
Buffer is part of the prelude and available without import.
Construction:
buf = Buffer.new() # empty buffer
buf = Buffer.withCapacity(1024u) # pre-allocate capacity (optimization hint)
buf = Buffer.from([0x48b, 0x69b]) # from a List[byte]
Buffer.withCapacity creates an empty buffer that has pre-allocated space for at least n bytes. The buffer's length is still 0 — capacity is an optimization hint to avoid repeated reallocations during sequential writes.
Bracket access:
val = buf[0] # byte — returns the element at index
buf[0] = 0xFFb # sets the element (requires mut)
Out-of-bounds access is a runtime error (panics). The index must be of type uint; only indices less than the buffer length are valid.
Methods:
| Signature | Description |
|---|---|
fn new() -> Buffer |
Static constructor. Returns an empty buffer. |
fn withCapacity(n: uint) -> Buffer |
Static constructor. Returns an empty buffer with pre-allocated capacity for at least n bytes. |
fn from(bytes: List[byte]) -> Buffer |
Static constructor. Returns a buffer containing the given bytes. |
fn length(self) -> uint |
Number of bytes. |
fn isEmpty(self) -> bool |
true if length is 0. |
fn get(self, index: uint) -> Option[byte] |
Return the byte at index, or None if out of bounds. |
fn push(mut self, value: byte) |
Append a byte to the end. |
fn pop(mut self) -> Option[byte] |
Remove and return the last byte, or None if empty. |
fn clear(mut self) |
Remove all bytes, leaving the buffer empty. |
fn slice(self, start: uint, end: uint) -> Buffer |
Return a new buffer containing bytes from start (inclusive) to end (exclusive). Panics if start > end or end > length. |
fn concat(self, other: Buffer) -> Buffer |
Return a new buffer with all bytes of self followed by all bytes of other. |
fn toList(self) -> List[byte] |
Return the contents as a List[byte]. |
fn toStr(self) -> Result[str, str] |
Validate contents as UTF-8 and return a str. Returns Err with a description if the bytes are not valid UTF-8. |
Endian-aware write methods (append):
These methods encode an integer value into bytes and append them to the end of the buffer. LE = little-endian (least significant byte first), BE = big-endian (most significant byte first).
| Signature | Description |
|---|---|
fn writeUint16LE(mut self, value: uint) |
Append value as 2 bytes, little-endian. Panics if value > 65535. |
fn writeUint16BE(mut self, value: uint) |
Append value as 2 bytes, big-endian. Panics if value > 65535. |
fn writeUint32LE(mut self, value: uint) |
Append value as 4 bytes, little-endian. Panics if value > 4294967295. |
fn writeUint32BE(mut self, value: uint) |
Append value as 4 bytes, big-endian. Panics if value > 4294967295. |
fn writeUint64LE(mut self, value: uint) |
Append value as 8 bytes, little-endian. |
fn writeUint64BE(mut self, value: uint) |
Append value as 8 bytes, big-endian. |
fn writeInt16LE(mut self, value: int) |
Append value as 2 bytes, little-endian. Panics if outside −32768..32767. |
fn writeInt16BE(mut self, value: int) |
Append value as 2 bytes, big-endian. Panics if outside −32768..32767. |
fn writeInt32LE(mut self, value: int) |
Append value as 4 bytes, little-endian. Panics if outside −2147483648..2147483647. |
fn writeInt32BE(mut self, value: int) |
Append value as 4 bytes, big-endian. Panics if outside −2147483648..2147483647. |
fn writeInt64LE(mut self, value: int) |
Append value as 8 bytes, little-endian. |
fn writeInt64BE(mut self, value: int) |
Append value as 8 bytes, big-endian. |
Endian-aware put methods (write at offset):
These methods encode an integer value and overwrite bytes at a specific offset in the buffer. The buffer must already contain enough bytes — put methods do not grow the buffer. Panics if offset + size > length (where size is 2, 4, or 8 bytes depending on the method). Value range checks are the same as the corresponding write methods.
| Signature | Description |
|---|---|
fn putUint16LE(mut self, offset: uint, value: uint) |
Write value as 2 bytes at offset, little-endian. |
fn putUint16BE(mut self, offset: uint, value: uint) |
Write value as 2 bytes at offset, big-endian. |
fn putUint32LE(mut self, offset: uint, value: uint) |
Write value as 4 bytes at offset, little-endian. |
fn putUint32BE(mut self, offset: uint, value: uint) |
Write value as 4 bytes at offset, big-endian. |
fn putUint64LE(mut self, offset: uint, value: uint) |
Write value as 8 bytes at offset, little-endian. |
fn putUint64BE(mut self, offset: uint, value: uint) |
Write value as 8 bytes at offset, big-endian. |
fn putInt16LE(mut self, offset: uint, value: int) |
Write value as 2 bytes at offset, little-endian. |
fn putInt16BE(mut self, offset: uint, value: int) |
Write value as 2 bytes at offset, big-endian. |
fn putInt32LE(mut self, offset: uint, value: int) |
Write value as 4 bytes at offset, little-endian. |
fn putInt32BE(mut self, offset: uint, value: int) |
Write value as 4 bytes at offset, big-endian. |
fn putInt64LE(mut self, offset: uint, value: int) |
Write value as 8 bytes at offset, little-endian. |
fn putInt64BE(mut self, offset: uint, value: int) |
Write value as 8 bytes at offset, big-endian. |
Endian-aware read methods (read at offset):
These methods decode an integer value from bytes at a specific offset in the buffer. They do not modify the buffer. Panics if offset + size > length.
| Signature | Description |
|---|---|
fn readUint16LE(self, offset: uint) -> uint |
Read 2 bytes at offset as a uint, little-endian. |
fn readUint16BE(self, offset: uint) -> uint |
Read 2 bytes at offset as a uint, big-endian. |
fn readUint32LE(self, offset: uint) -> uint |
Read 4 bytes at offset as a uint, little-endian. |
fn readUint32BE(self, offset: uint) -> uint |
Read 4 bytes at offset as a uint, big-endian. |
fn readUint64LE(self, offset: uint) -> uint |
Read 8 bytes at offset as a uint, little-endian. |
fn readUint64BE(self, offset: uint) -> uint |
Read 8 bytes at offset as a uint, big-endian. |
fn readInt16LE(self, offset: uint) -> int |
Read 2 bytes at offset as an int, little-endian (sign-extended). |
fn readInt16BE(self, offset: uint) -> int |
Read 2 bytes at offset as an int, big-endian (sign-extended). |
fn readInt32LE(self, offset: uint) -> int |
Read 4 bytes at offset as an int, little-endian (sign-extended). |
fn readInt32BE(self, offset: uint) -> int |
Read 4 bytes at offset as an int, big-endian (sign-extended). |
fn readInt64LE(self, offset: uint) -> int |
Read 8 bytes at offset as an int, little-endian. |
fn readInt64BE(self, offset: uint) -> int |
Read 8 bytes at offset as an int, big-endian. |
Buffer also inherits the following methods from Iterable[byte] (stdlib/interfaces.md): map, flatMap, filter, reduce, find, any, all, join, each, enumerate. The map, filter, flatMap, and enumerate methods return lazy Iterator values; use toList() to materialize.
Concatenation:
combined = buf1.concat(buf2)
Buffer concatenation is an explicit method call. The + operator is not overloaded for buffers.
Iteration:
for b in buf
println("{b}")
end
for (i, b) in buf.enumerate()
println("{i}: {b}")
end
The for loop calls iter(), which returns an Iterator[byte]. Each element has type byte.
Structurally modifying a buffer (e.g., push, pop, clear) during iteration is a runtime panic. Element-level mutation via bracket assignment is safe.
Interface conformance:
| Interface | Condition |
|---|---|
PartialEq[Buffer] |
always — byte-wise equality, same length |
Eq[Buffer] |
always |
Iterable[byte] |
always — iter() iterates over bytes |
ToString |
always — output format is implementation-defined and intended for diagnostic purposes only, not for serialization or user-facing display |
Examples:
# Building a buffer manually
mut buf = Buffer.new()
buf.push(0x48b) # 'H'
buf.push(0x69b) # 'i'
buf.toStr() # Ok("Hi")
# From a byte list
buf = Buffer.from([72b, 101b, 108b, 108b, 111b])
buf.toStr() # Ok("Hello")
buf.length() # 5u
# Bracket access
buf[0] # 72b
buf.get(99u) # None
# Slicing
header = buf.slice(0u, 4u) # Buffer containing [72, 101, 108, 108]
header.length() # 4u
# Endian-aware encoding
mut out = Buffer.new()
out.writeUint32LE(0x01020304u) # appends [0x04, 0x03, 0x02, 0x01]
out.writeUint16BE(256u) # appends [0x01, 0x00]
out.length() # 6u
# Reading back
out.readUint32LE(0u) # 0x01020304u
out.readUint16BE(4u) # 256u
# Backpatching: write a placeholder, then fill it in later
mut code = Buffer.new()
code.writeUint32LE(0u) # placeholder for jump offset at position 0
code.push(0x90b) # some instruction bytes
code.push(0x90b)
code.putUint32LE(0u, 6u) # backpatch: jump target is offset 6
code.readUint32LE(0u) # 6u