Skip to content
CryoCryo home
Stdlibcollections

string

import std::collections::string; · source

String<A>

type struct String<A = GlobalAlloc> {
    buffer: RawBuffer<u8, A>;
    length: u64;

    static new() -> String;
    static new_in(alloc: A) -> String<A>;
    static with_capacity(capacity: u64) -> String;
    static try_with_capacity_in(capacity: u64, alloc: A) -> Result<String<A>, AllocError>;
    static from_str(source: Str) -> String;
    ![implicit]
    static from_string(text: string) -> String;
    static with_null(source: Str) -> String;
    static from<T>(item: T) -> String;
    push<T>(mut &this, item: T) -> void;
    try_push<T>(mut &this, item: T) -> Result<(), AllocError>;
    push_byte(mut &this, byte: u8) -> void;
    try_push_byte(mut &this, byte: u8) -> Result<(), AllocError>;
    clear(mut &this) -> void;
    length(&this) -> u64;
    capacity(&this) -> u64;
    is_empty(&this) -> boolean;
    as_str(&this) -> Str;
    as_bytes(&this) -> Slice<u8>;
    as_ptr(&this) -> u8*;
    as_cstr(mut &this) -> u8*;
    into_raw(mut this) -> string;
    starts_with(&this, prefix: &Str) -> boolean;
    ends_with(&this, suffix: &Str) -> boolean;
    find(&this, needle: &Str) -> Option<u64>;
    contains(&this, needle: &Str) -> boolean;
    trim(&this) -> Str;
    trim_start(&this) -> Str;
    trim_end(&this) -> Str;
    to_ascii_uppercase(&this) -> String;
    to_ascii_lowercase(&this) -> String;
    split(&this, sep: &Str) -> SplitIter;
    chars(&this) -> Chars;
    char_indices(&this) -> CharIndices;
    truncate(mut &this, new_length: u64) -> void;
    reserve(mut &this, additional: u64) -> Result<(), AllocError>;
    reserve_exact(mut &this, additional: u64) -> Result<(), AllocError>;
    shrink_to_fit(mut &this) -> void;
}

The owned, growable companion to Str: a heap byte buffer plus a length. No NUL terminator, no encoding assumptions beyond "the bytes are valid UTF-8". The first allocation reserves 8 bytes.

Constructing

ConstructorNotes
new() / new_in(alloc)Empty. No heap storage until the first push.
with_capacity(capacity)Preallocated. try_with_capacity_in is the fallible form.
from_str(source: Str)Copy a borrowed view into owned storage.
from_string(text: string)Copy a C string. Marked ![implicit], so mut s: String = "text" and println("text") both route through it.
from<T>(item)The general constructor — same dispatch as push.
with_null(source: Str)Owned copy that keeps a trailing NUL for the FFI boundary.

Appending

push<T> appends item as its text representation, dispatched at compile time through static match (T) — no runtime cost and no trait bound, because the available arms are the accepted types:

  • String, Str, and string — the UTF-8 bytes verbatim (a string's terminating NUL is not copied).
  • Every primitive integer, usize, and isize — its decimal text. s.push(65 as u8) appends "65".
  • f32 and f64 — their Display text.
  • boolean"true" or "false".

Anything else is a compile error; the static match has no _ arm.

mut s: String = String::new();
s.push("count: ");
s.push(42);            // "count: 42"
s.push_byte(0x0A);     // a raw newline byte

push_byte appends a single raw byte rather than its decimal text — for NUL terminators, control characters, and binary buffers. Keeping the result valid UTF-8 is your responsibility. Both have try_ forms returning Result<(), AllocError> instead of panicking.

Reading and borrowing

length(), capacity(), is_empty(), as_str() -> Str, as_bytes() -> Slice<u8>, as_ptr() -> u8*, plus clear(), truncate(new_length), reserve, reserve_exact, and shrink_to_fit.

The Str conveniences are forwarded so you don't write s.as_str().starts_with(...) everywhere: starts_with, ends_with, find, contains, trim, trim_start, trim_end, to_ascii_uppercase, to_ascii_lowercase, split, chars, and char_indices. Everything they return borrows this string's buffer and is valid only while it lives unmutated.

Crossing into C

A String built by push carries no trailing NUL, so as_ptr() alone is not a valid C string. Two methods bridge the gap:

  • as_cstr(mut &this) -> u8* borrows the buffer as a NUL-terminated C string. It writes the terminator at index length — reserving one spare byte if the buffer is full — without changing the logical length. Idempotent and zero-allocation once the spare byte exists. The pointer is valid until the next mutating call and must not be freed by the caller.
  • into_raw(mut this) -> string consumes the string, appends a terminator, and hands back the raw buffer, leaking the allocation so the caller owns the bytes outright.

As in C, an interior NUL ends the string early; the bytes are not otherwise validated.

Trait implementations

implement<A> trait Eq for struct String<A>
where A: Allocator

implement<A> trait Hash for struct String<A>
where A: Allocator

implement<A> trait Ord for struct String<A>
where A: Allocator

implement<A> trait Drop for struct String<A>
where A: Allocator

implement trait Clone for struct String<GlobalAlloc>

implement trait Default for struct String<GlobalAlloc>

implement<A> trait Display for struct String<A>
where A: Allocator   // std::fmt::display

implement trait Debug for struct String<GlobalAlloc>   // std::fmt::display

implement trait FmtWrite for struct String<GlobalAlloc>   // std::fmt::write

Eq, Ord, and Hash agree with Str's, so a String and a Str holding the same bytes hash and compare identically. FmtWrite is what lets a String be the sink of a Formatterformat_to_string is built on it.