Module string/string_builder

string/string_builder
Stability: unstable — the core (`new`, `write_str`, `write_string`, `write_byte`, `write_rune`, `len`, `to_string`) is settled and heavily used, but the helpers transplanted from `Writer` are not. `write_hex` and `write_f64` render through a fixed-size stack buffer and TRUNCATE silently rather than growing it (`write_f64(f64(1.0e300), i32(2))` yields 63 digits of a 302-digit number — `issues/stddoc-str-string-builder-write-f64-truncates.md`), and `clear` releases the buffer where Rust's `String::clear` keeps the capacity (`issues/stddoc-str-string-builder-clear-drops-capacity.md`). Freezing follows fixing those two and deciding whether number formatting belongs on a text builder at all — it is here because of a dependency direction, not because it was designed here. — stable modules only change additively; this one may still change.

Mutable UTF-8 string builder for efficient incremental construction.

StringBuilder is the accumulator to reach for when a String is assembled from many parts in a loop: appending is amortised O(1) into one growing ArrayList(u8), and to_string() hands that buffer over instead of copying it, so building an N-byte string costs O(N) once rather than twice. Repeated a + b on String is what it replaces — that allocates a new string per concatenation.

It also carries the three number/field renderers that used to live on std/fmt's Writer (write_hex, write_f64, write_padded), which retired into this type in v0.2.28 (#511). They sit in std/string only because std/fmt already depends on std/string and the other direction would be a cycle; std/fmt re-exports StringBuilder and Alignment so a caller formatting text need not know that.

Lengths here are BYTES — len() is the buffer's byte count, the same basis as String.len() (see docs/en-US/STRINGS.md). The one exception is write_padded, whose width is a RUNE count so that it agrees with FormatSpec.

Stability

unstable — the core (new, write_str, write_string, write_byte, write_rune, len, to_string) is settled and heavily used, but the helpers transplanted from Writer are not. write_hex and write_f64 render through a fixed-size stack buffer and TRUNCATE silently rather than growing it (write_f64(f64(1.0e300), i32(2)) yields 63 digits of a 302-digit number — issues/stddoc-str-string-builder-write-f64-truncates.md), and clear releases the buffer where Rust's String::clear keeps the capacity (issues/stddoc-str-string-builder-clear-drops-capacity.md). Freezing follows fixing those two and deciding whether number formatting belongs on a text builder at all — it is here because of a dependency direction, not because it was designed here.

Types

Alignment enum
Alignment

Where the text sits inside a padded field — the argument to write_padded, and the same three cases FormatSpec parses from < / > / ^.

It lives here rather than in std/fmt because write_padded does, and std/fmt already depends on std/string; the other direction would be a cycle. std/fmt re-exports it, so importing it from std/fmt works too.

Variants

VariantFieldsDescription
Left
Right
Center
StringBuilder object
StringBuilder

Mutable buffer for building a String incrementally.

Use StringBuilder when you need to construct a string from many parts, appending bytes or strings in a loop, before converting to an immutable String with to_string().

Example

sb := StringBuilder.new();
sb.write_str("Hello");
sb.write_str(", ");
sb.write_string(`world`);
sb.write_byte(u8(33));  // '!'
result := sb.to_string();
assert(result == `Hello, world!`, "built string");

Fields

NameTypeDescription
_bufArrayList(u8)

Trait Implementations

impl(StringBuilder, ...)
new : (StringBuilder) fn() -> StringBuilder

Create a new, empty StringBuilder.

Returns: StringBuilder

with_capacity : (StringBuilder) fn(capacity : usize) -> StringBuilder

Create a StringBuilder pre-allocated for capacity bytes.

Parameters

NameTypeNotes
capacityusize

Returns: StringBuilder

len : (StringBuilder) fn(self : StringBuilder) -> usize

Returns the current number of bytes in the buffer.

Parameters

NameTypeNotes
selfStringBuilder

Returns: usize

is_empty : (StringBuilder) fn(self : StringBuilder) -> bool

Returns true if the buffer is empty.

Parameters

NameTypeNotes
selfStringBuilder

Returns: bool

write_str : (StringBuilder) fn(self : StringBuilder, s : str) -> unit

Append a str (raw byte slice) to the buffer.

Parameters

NameTypeNotes
selfStringBuilder
sstr

Returns: unit

write_string : (StringBuilder) fn(self : StringBuilder, s : String) -> unit

Append a String to the buffer.

Parameters

NameTypeNotes
selfStringBuilder
sString

Returns: unit

write_byte : (StringBuilder) fn(self : StringBuilder, b : u8) -> unit

Append a single byte to the buffer.

Parameters

NameTypeNotes
selfStringBuilder
bu8

Returns: unit

write_rune : (StringBuilder) fn(self : StringBuilder, r : rune) -> unit

Append a single Unicode code point, encoded as UTF-8.

Example

sb := StringBuilder.new();
sb.write_rune(rune(0x1F600));  // 😀
sb.write_rune(rune(0x41));     // 'A'

Parameters

NameTypeNotes
selfStringBuilder
rrune

Returns: unit

write_line : (StringBuilder) fn(self : StringBuilder, s : String) -> unit

Append a String followed by a newline byte (\n).

Parameters

NameTypeNotes
selfStringBuilder
sString

Returns: unit

to_string : (StringBuilder) fn(self : StringBuilder) -> String

Detach the accumulated bytes as a String, leaving the builder EMPTY and still usable.

It does not copy and it does not consume the builder: the receiver is a reference, and it starts over with a fresh buffer, so building an N-byte string costs O(N) once. The returned String is therefore independent — a later write_* on the same builder cannot mutate a string already handed to a caller.

Parameters

NameTypeNotes
selfStringBuilder

Returns: String

write_hex : (StringBuilder) fn(self : StringBuilder, n : u64) -> unit

Append an unsigned 64-bit integer in lowercase hexadecimal.

Parameters

NameTypeNotes
selfStringBuilder
nu64

Returns: unit

write_f64 : (StringBuilder) fn(self : StringBuilder, n : f64, precision : i32) -> unit

Append n with exactly precision decimal places.

Parameters

NameTypeNotes
selfStringBuilder
nf64
precisioni32

Returns: unit

write_padded : (StringBuilder) fn(self : StringBuilder, s : str, width : usize, pad : rune, align : Alignment) -> unit

Append s padded to width RUNES with pad, aligned per align. A s already at or over the width is written unpadded.

Width is a RUNE count, matching FormatSpec's {:width$} and Rust's. It used to be a BYTE count here, so write_padded("héllo", 8, ' ', .Left) emitted two spaces instead of three and the column did not line up — the two width bases in one module disagreed (issues/fixed/write-padded-counted-bytes-where-formatspec-counts-runes.md).

Parameters

NameTypeNotes
selfStringBuilder
sstr
widthusize
padrune
alignAlignment

Returns: unit

clear : (StringBuilder) fn(self : StringBuilder) -> unit

Empty the builder.

This RELEASES the buffer rather than retaining its capacity — unlike Rust's String::clear and unlike ArrayList.clear, both of which keep the allocation for reuse. A builder cleared in a loop therefore reallocates from zero on every pass; when that matters, keep a fresh builder per iteration instead (it costs the same) or hand the bytes off with to_string(), which detaches for the same price. (issues/stddoc-str-string-builder-clear-drops-capacity.md)

Parameters

NameTypeNotes
selfStringBuilder

Returns: unit

impl(StringBuilder, Default(...))
default : (StringBuilder) fn() -> StringBuilder

The default value of the type.

Returns: StringBuilder