Skip to content

BinBuf

Mutable byte buffer; the mutable counterpart to Bin.

A buffer is an Io that only writes, appending what it is given, so it can collect the output of anything that writes to a stream:

let buf = BinBuf()
run uname -r stdout: $buf
let release = buf.freeze_str()

To read, overwrite or seek within a buffer, use an io.Cursor.

Inherits from: io.Io

Implements: Index[Int], Assign[Int]

Constructor

BinBuf …

Builds a buffer, optionally seeded with the contents of existing binary data.

Parameters

NameTypeDescription
initial? Bin initial contents

Example

let buf = BinBuf(b"hello")
assert_eq $buf.len 5

Fields

len @ Int [get]

Returns the byte length of the buffer's current contents.

Example
assert_eq (BinBuf(b"hello").len) 5
writable @ Bool [get]

Always true.

Methods

(assign)[K] key value overload 1 of 2

Assigns a byte or byte range. Range assignment may grow or shrink the buffer.

let buf = BinBuf(b"foobar")
buf[0] = 70
buf[1..3] = b"XYZ"
assert_eq $buf.freeze() b"FXYZbar"

Parameters

NameTypeDescription
key K
value AssignItem[{*Int}, K]

(index)[K] key -> IndexItem[{*Int}, K] overload 1 of 2

Unlike StrBuf, BinBuf supports both scalar and range indexing and indexing:

let buf = BinBuf(b"foobar")
assert_eq $buf[0] 102
assert_eq $buf[2..4] b"ob"

Parameters

NameTypeDescription
key K

append value

Appends value to the buffer. Str/Bin input is copied byte-for-byte (round-tripping non-UTF-8 bytes exactly); anything else is converted the same way str would convert it, written directly into the buffer.

Parameters

NameTypeDescription
value Value value to append

Example

let buf = BinBuf()
buf.append b"foo"
buf.append "bar"
buf.append 42
assert_eq $buf.freeze() b"foobar42"

clear()

Empties the buffer, retaining its allocated capacity.

let buf = BinBuf(b"foobar")
buf.clear()
assert_eq $buf.len 0
buf.append b"x"
assert_eq $buf.freeze() b"x"

contains needle -> Bool

Tests whether the buffer's contents contain the given bytes.

Parameters

NameTypeDescription
needle Bin the bytes to find

Example

assert (BinBuf(b"foobar").contains b"oob")

drain … -> Iter[Bin]

Returns an iterator that removes and yields up to size bytes at a time from the front of the buffer as it's consumed.

Parameters

NameTypeDescription
size? Int Maximum bytes per chunk; 512 KiB when omitted.

Example

let buf = BinBuf(b"hello world")
assert_eq [...buf.drain(4)] [b"hell", b"o wo", b"rld"]
assert_eq $buf.len 0

Draining doesn't move the remaining contents for each chunk, so its cost grows with the bytes drained, not with what is left. Indexes given to other methods count from the start of what remains. Several drain iterators over one buffer take turns removing from the same content.

ends_with suffix -> Bool

Tests whether the buffer's contents end with the given suffix.

Parameters

NameTypeDescription
suffix Bin the suffix bytes

Example

assert (BinBuf(b"foobar").ends_with b"bar")

extend value

Appends the raw bytes of value, which must be a Str or Bin.

Parameters

NameTypeDescription
value (Bin | Str)

Example

let buf = BinBuf(b"foo")
buf.extend b"bar"
assert_eq $buf.freeze() b"foobar"

flush()

Does nothing, since writes are never held back.

freeze() -> Bin

Converts the buffer's current contents into an immutable Bin in place, without copying, and empties the buffer. The buffer stays usable afterward, and the returned value is unaffected by later mutation.

Example

let buf = BinBuf(b"abc")
let frozen = buf.freeze()
assert_eq $frozen b"abc"
assert_eq $buf.len 0
buf.append b"def"
assert_eq $frozen b"abc"

freeze_str() -> Str

Converts the buffer's current contents into an immutable Str without copying, and empties the buffer, as freeze does.

The contents are checked as UTF-8 only here, so text written in pieces that split characters is collected intact.

Errors

Raises a RuntimeError if the contents are not valid UTF-8, leaving them in the buffer.

Example

let buf = BinBuf()
buf.write b"caf\xc3"
buf.write b"\xa9"
assert_eq $buf.freeze_str() "café"

insert index value

Inserts value at the given byte index, shifting the rest of the buffer right in place. value may be a single byte value, or a Str/Bin slice.

Parameters

NameTypeDescription
index Int insertion point
value (Int | Bin) Byte value (0-255) or binary data.

Example

let buf = BinBuf(b"foobar")
buf.insert 3 b"XYZ"
buf.insert 0 65
assert_eq $buf.freeze() b"AfooXYZbar"

push *bytes

Appends one or more raw byte values to the buffer.

Parameters

NameTypeDescription
*bytes Int byte values (0-255) to append

Example

let buf = BinBuf()
buf.push 104 105
assert_eq $buf.freeze() b"hi"

remove index_or_range -> (Int | Bin)

Removes and returns a byte or a range of bytes, shifting the rest of the buffer left in place. An Int index removes and returns a single byte; a Range removes and returns a Bin of the removed bytes.

Parameters

NameTypeDescription
index_or_range (Int | Range[Int])

Example

let buf = BinBuf(b"foobar")
assert_eq (buf.remove 0) 102
assert_eq $buf.freeze() b"oobar"

let buf2 = BinBuf(b"foobar")
assert_eq (buf2.remove (1..3)) b"oo"
assert_eq $buf2.freeze() b"fbar"

starts_with prefix -> Bool

Tests whether the buffer's contents start with the given prefix.

Parameters

NameTypeDescription
prefix Bin the prefix bytes

Example

assert (BinBuf(b"foobar").starts_with b"foo")

truncate len

Shrinks the buffer to len bytes, discarding anything past that point.

Parameters

NameTypeDescription
len Int new length

Example

let buf = BinBuf(b"foobar")
buf.truncate 3
assert_eq $buf.freeze() b"foo"

write *data -> Int

Appends data, given in pieces.

Parameters

NameTypeDescription
*data (Str | Bin) Data to append.

Returns

The number of bytes appended, which is all of them.