Bytes
API summary (generated from the Beans source by npm run coverage): 1 type · 3 static methods · 29 instance methods.
Bytes is a growable, changeable buffer of raw bytes. Use it to build binary
data, read fixed-width integers out of a buffer, or collect text before turning it
into a string.
Unlike string, a Bytes value can change in
place. Every method that changes the buffer returns the same buffer, so you can
chain calls.
Bytes is a native builtin with no .b source, reached through the runtime ABI
table in compiler/beans/expression.b.
Its signatures are positional: the type in each slot is fixed, the names are not.
Making a Bytes
Section titled “Making a Bytes”Construct a fresh buffer with new Bytes(n), which gives n zeroed bytes and
panics on a negative n. Three statics build or measure buffers:
Bytes.from(string) -> BytesBytes.from_raw(RawPtr<u8>, int) -> BytesBytes.uvarint_size(int) -> intBytes.from(s)returns a new buffer holding a copy of strings’s bytes.Bytes.from_raw(pointer, len)copieslenbytes from a raw pointer without taking ownership. It requiresunsafe; a null pointer is accepted only whenlenis zero.Bytes.uvarint_size(v)returns how many bytesvwould take as an unsigned varint, without writing anything.
let buf: Bytes = new Bytes(0)let text: Bytes = Bytes.from("hello")Methods
Section titled “Methods”Bytes.len() -> intBytes.as_ptr() -> RawPtr<u8>Bytes.reserve(int) -> BytesBytes.resize(int) -> BytesBytes.fill(int) -> BytesBytes.get(int) -> intBytes.set(int, int) -> BytesBytes.push(int) -> BytesBytes.get_u8(int) -> intBytes.get_u16(int) -> intBytes.get_u32(int) -> intBytes.get_u64(int) -> intBytes.get_i64(int) -> intBytes.put_u8(int, int) -> BytesBytes.put_u16(int, int) -> BytesBytes.put_u32(int, int) -> BytesBytes.put_u64(int, int) -> BytesBytes.put_i64(int, int) -> BytesBytes.slice(int, int) -> BytesBytes.copy_from(Bytes, int) -> BytesBytes.append(Bytes) -> BytesBytes.append_string(string) -> BytesBytes.append_i64(int) -> BytesBytes.append_range(Bytes, int, int) -> BytesBytes.to_string() -> stringBytes.to_string_until_nul() -> stringBytes.append_uvarint(int) -> BytesBytes.get_uvarint(int) -> intBytes.crc32(int, int) -> intSize and shape
Section titled “Size and shape”len()is the number of bytes.as_ptr()borrows the buffer’s raw pointer and requiresunsafe. The pointer is null for an empty buffer. Keep theBytesalive, do not free the pointer, and do not resize, reserve, append, or push while using it.reserve(n)makes room for at leastnbytes without changing the length.resize(n)grows or shrinks the buffer tonbytes; new bytes read as zero.fill(v)sets every existing byte tov.
Single bytes
Section titled “Single bytes”get(i)returns the byte atias an integer, and panics ifiis out of range.set(i, v)writes the byte ati, and panics ifiis out of range.push(v)adds one byte at the end, growing the buffer.
Fixed-width integers (little-endian)
Section titled “Fixed-width integers (little-endian)”The get_* readers return a whole number read at a byte position, and the put_*
writers write one at a position. All are little-endian and panic when the position
plus the width runs past the end of the buffer. put_* returns the buffer, so
writes chain.
Copying and appending
Section titled “Copying and appending”slice(from, to)returns a new buffer with the bytes in[from, to).copy_from(src, at)copies all ofsrc’s bytes into this buffer starting atat.append(other)adds another buffer’s bytes at the end;append_string(s)adds a string’s bytes;append_i64(v)addsvas 8 little-endian bytes; andappend_range(src, from, to)addssrc’s bytes in[from, to).
Turning bytes into text
Section titled “Turning bytes into text”to_string()returns every byte as a string, including any NUL bytes.to_string_until_nul()stops at the first NUL byte. The names say which one you get, so a binary-safe reader cannot pick the truncating form by accident.
Varints and checksums
Section titled “Varints and checksums”A varint is a compact way to store an integer using fewer bytes for small values. Beans uses unsigned LEB128 over the full 64-bit pattern, so a negative value takes 10 bytes.
append_uvarint(v)addsvas an unsigned varint.get_uvarint(pos)reads an unsigned varint that starts atpos. Advance your own position byBytes.uvarint_size(v)to read the next one.crc32(from, to)returns the IEEE CRC-32 checksum of the bytes in[from, to).
Comparing
Section titled “Comparing”== and != compare two Bytes by value: same length and same bytes.
Examples
Section titled “Examples”Build a record by chaining, then read it back:
import std.io
fn main() { let buf: Bytes = new Bytes(0) buf.append_string("id=").append_i64(42).push(10) io.println("{buf.len()} bytes")
let header: Bytes = new Bytes(8) header.put_u32(0, 65535).put_u32(4, 7) io.println("{header.get_u32(0)} {header.get_u32(4)}")
let text: Bytes = Bytes.from("hello") io.println(text.to_string())}Write a run of varints, then walk them back out with uvarint_size:
import std.io
fn main() { var rec: Bytes = new Bytes(0) rec.append_uvarint(1).append_uvarint(300).append_uvarint(70000)
var pos: int = 0 var seen: List<int> = [] for seen.len() < 3 { let v: int = rec.get_uvarint(pos) seen.push(v) pos = pos + Bytes.uvarint_size(v) } io.println(seen)
let check: Bytes = Bytes.from("123456789") io.println("crc32 {check.crc32(0, check.len())}")}See also
Section titled “See also”- string, immutable text.
- Files and mapping,
File.readandFile.writeuseBytes.