Module string/string_builder

string/string_builder
Stability: unstable — may still change; see below.

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/fixed/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
Methods
clone : (Alignment) fn(inout(self) : Alignment) -> Alignment

Parameters

NameTypeNotes
selfAlignment

Returns: Alignment

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

NameTypeNotesDescription
capacityusize

Returns the current number of bytes in the buffer. Bytes the builder can hold before it must grow — Rust's String::capacity. with_capacity could be SET but never read, which made the clear contract (capacity survives, length does not) unobservable and so untestable.

Returns: StringBuilder

new_in : (StringBuilder) fn(alloc : Allocator) -> StringBuilder

An empty builder whose buffer lives in alloc (see ArrayList.new_in). A String detached by to_string keeps that buffer, and the builder's next buffer comes from alloc too.

Parameters

NameTypeNotes
allocAllocator

Returns: StringBuilder

with_capacity_in : (StringBuilder) fn(alloc : Allocator, capacity : usize) -> StringBuilder

with_capacity with the buffer in alloc.

Parameters

NameTypeNotesDescription
allocAllocator
capacityusize

Returns the current number of bytes in the buffer. Bytes the builder can hold before it must grow — Rust's String::capacity. with_capacity could be SET but never read, which made the clear contract (capacity survives, length does not) unobservable and so untestable.

Returns: StringBuilder

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

Returns the current number of bytes in the buffer. Bytes the builder can hold before it must grow — Rust's String::capacity. with_capacity could be SET but never read, which made the clear contract (capacity survives, length does not) unobservable and so untestable.

Parameters

NameTypeNotes
selfStringBuilder

Returns: usize

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

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(inout(self) : StringBuilder, s : str) -> unit

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

Parameters

NameTypeNotes
selfStringBuilder
sstr

Returns: unit

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

Append a String to the buffer.

Parameters

NameTypeNotes
selfStringBuilder
sString

Returns: unit

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

Append a single byte to the buffer.

Parameters

NameTypeNotes
selfStringBuilder
bu8

Returns: unit

write_rune : (StringBuilder) fn(inout(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(inout(self) : StringBuilder, s : String) -> unit

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

Parameters

NameTypeNotes
selfStringBuilder
sString

Returns: unit

to_string : (StringBuilder) fn(inout(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(inout(self) : StringBuilder, n : u64) -> unit

Append an unsigned 64-bit integer in lowercase hexadecimal.

Parameters

NameTypeNotes
selfStringBuilder
nu64

Returns: unit

write_f64 : (StringBuilder) fn(inout(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(inout(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(inout(self) : StringBuilder) -> unit

Empty the builder, KEEPING its capacity for reuse — Rust's String::clear, and the same contract as ArrayList.clear.

len() becomes 0 while capacity() is unchanged, so a builder cleared in a loop allocates once rather than on every pass. Use to_string() when you want the bytes handed off instead; that detaches the buffer and the next write starts from nothing.

Until 2026-09-14 this released the buffer, contradicting its own doc comment (issues/fixed/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