Bytes
API summary (generated from the Beans source by npm run coverage): 1 type · 4 static methods · 30 instance methods.
Bytes is a move-only, growable buffer of raw bytes. It implements Send, so
one owner can move it to another thread, but it is not Sync and cannot be
shared for concurrent mutation. 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. Methods that change it return unit; call them as statements.
Bytes is a native builtin with no .b source, reached through the runtime ABI
table in src/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. Four statics build or measure buffers:
Bytes.from(string) -> BytesBytes.from_raw(RawPtr<u8>, int) -> BytesBytes.filled(int, 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.filled(length, value)createslengthbytes with every byte set tovalue. It is useful for a reusable socket read buffer.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)Bytes.resize(int)Bytes.fill(int)Bytes.get(int) -> Option<int>Bytes.set(int, int)Bytes.push(int)Bytes.get_u8(int) -> intBytes.get_u16(int) -> intBytes.get_u32(int) -> intBytes.get_u64(int) -> intBytes.get_i64(int) -> intBytes.put_u8(int, int)Bytes.put_u16(int, int)Bytes.put_u32(int, int)Bytes.put_u64(int, int)Bytes.put_i64(int, int)Bytes.slice(int, int) -> BytesBytes.copy_from(Bytes, int)Bytes.append(Bytes)Bytes.append_string(string)Bytes.append_int_text(int)Bytes.append_i64(int)Bytes.append_range(Bytes, int, int)Bytes.to_string() -> stringBytes.to_string_until_nul() -> stringBytes.append_uvarint(int)Bytes.get_uvarint(int) -> intBytes.crc32(int, int) -> intbytes[i] is a checked, required read: it returns int and panics out of
range. bytes[i] = value replaces an existing byte, like set(i, value).
Neither a read nor an indexed write grows the buffer; use push to append.
Compound bracket assignment is not supported.
Size 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)returnssome(byte)when present andnonefor a negative or out-of-range index. The byte is anintfrom 0 to 255.- To migrate a required
get(i)read from 0.1.53, usebytes[i].get_u8(i)also remains a required read and works with older compilers. 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.
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_int_text(v)adds the decimal text form of an integer;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.
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, then read it back:
import std.io
fn main() { let buf: Bytes = new Bytes(0) buf.append_string("id=") buf.append_i64(42) buf.push(10) io.println("{buf.len()} bytes")
let header: Bytes = new Bytes(8) header.put_u32(0, 65535) header.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) rec.append_uvarint(300) rec.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.