Skip to content

StrBuf

Mutable UTF-8 string buffer; the mutable counterpart to Str.

Implements: Index[Range[Int], Str], Assign[Range[Int], Str]

Constructor

StrBuf …

Builds a buffer, optionally seeded with the contents of an existing string.

Parameters

NameTypeDescription
initial? Str initial contents

Example

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

Methods

(assign) index value

Assigns through an index.

(index) index

StrBuf supports only range indexing and assignment, matching Str — a single UTF-8 code unit is rarely a useful result on its own:

let buf = StrBuf("foobar")
assert_eq $buf[2..4] "ob"
buf[1..3] = "XYZ"
assert_eq $buf.freeze() "fXYZbar"

Range assignment may grow or shrink the buffer: the replacement doesn't need to be the same length as the range it replaces. Both the range and the assigned value's boundaries must land on UTF-8 code point boundaries.

(sink)()

StrBuf is a sink, so it can be the target of a pipeline, of strand.put, or of a run redirect. put is append: the value's string form goes in verbatim, with no line terminator added.

let buf = StrBuf()
run uname -r stdout: $buf

Line termination is the caller's to choose, so a StrBuf can stand in for any other sink without changing what gets written:

let buf = StrBuf()
let out = buf.precrimp()
out.put "first"
out.put "second"
assert_eq $buf.freeze() "first\nsecond\n"

append value

Appends value to the buffer. Str input is copied byte-for-byte; anything else is converted the same way str would convert it, written directly into the buffer.

Parameters

NameTypeDescription
value value to append

Example

let buf = StrBuf()
buf.append "foo"
buf.append 42
assert_eq $buf.freeze() "foo42"

clear()

Empties the buffer, retaining its allocated capacity.

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

contains needle -> Bool

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

Parameters

NameTypeDescription
needle Str the substring to find

Example

assert (StrBuf("foobar").contains "oob")

drain … -> Iter[Str]

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

Each chunk boundary is rounded down to the nearest UTF-8 code point boundary, unless that would produce an empty chunk (size smaller than the first remaining code point), in which case it rounds up instead so every chunk yielded is non-empty.

Parameters

NameTypeDescription
size? Int maximum bytes per chunk (defaults to 512 KiB)

Example

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

Draining never shifts the buffer's remaining contents proportionally to their length: consumed bytes are dropped by advancing an internal cursor, not by copying the tail down on every chunk. Other mutating methods (and freeze) settle this cursor transparently before they run, so indices passed to them are always relative to the buffer's current (undrained) content. Multiple drain iterators created from the same buffer share this cursor, so they interleave draining the same content rather than each redraining it independently.

ends_with suffix -> Bool

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

Parameters

NameTypeDescription
suffix Str the suffix string

Example

assert (StrBuf("foobar").ends_with "bar")

extend value

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

Parameters

NameTypeDescription
value Str string to append

Example

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

freeze() -> Str

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

Example

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

insert index value

Inserts value at the given byte index, shifting the rest of the buffer right in place.

Parameters

NameTypeDescription
index Int insertion point; must fall on a UTF-8 boundary
value Str string to insert

Example

let buf = StrBuf("foobar")
buf.insert 3 "XYZ"
assert_eq $buf.freeze() "fooXYZbar"

len() -> Int

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

Example

assert_eq (StrBuf("hello").len) 5

remove range -> Str

Removes and returns the substring covered by range, shifting the rest of the buffer left in place.

Parameters

NameTypeDescription
range Range[Int] byte range to remove; must fall on UTF-8 boundaries

Example

let buf = StrBuf("foobar")
assert_eq (buf.remove (1..3)) "oo"
assert_eq $buf.freeze() "fbar"

Unlike insert, remove only accepts a range — a scalar index would remove a single UTF-8 code unit, which is rarely a useful result.

starts_with prefix -> Bool

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

Parameters

NameTypeDescription
prefix Str the prefix string

Example

assert (StrBuf("foobar").starts_with "foo")

truncate len

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

Parameters

NameTypeDescription
len Int new length; must fall on a UTF-8 boundary

Example

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