Skip to content

str::into_string

str methods · Strings

Level: reference · for working programmers

One line: Turns a Box<str> into a String without copying — the same allocation, given back its spare capacity field.

pub fn into_string(self: Box<Self>) -> String

Stable since 1.4.0.

It is defined on Box<str>, not on &str, so it is called as boxed.into_string() and consumes the box. That is the trip back from String::into_boxed_str, and both directions are O(1): the bytes never move.

The pair exists because the two types trade the same memory for different guarantees. String carries a capacity field so it can grow; Box<str> drops it, saving eight bytes per value and giving up growth. In a struct held a million times, that is eight megabytes.

Do not confuse it with ToString::to_string, which copies a &str into a fresh allocation. This one moves.

Example

str_into_string.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    let s = String::from("hello");
    let boxed: Box<str> = s.into_boxed_str();
    println!("{boxed:?}");

    // And back, without copying.
    let back: String = boxed.into_string();
    println!("{back:?} capacity {}", back.capacity());

    // The size difference that motivates Box<str>.
    println!("String   {} bytes", std::mem::size_of::<String>());
    println!("Box<str> {} bytes", std::mem::size_of::<Box<str>>());

    // A String with slack loses it on the way out and comes back tight.
    let mut roomy = String::with_capacity(64);
    roomy.push_str("small");
    println!("before {} / {}", roomy.len(), roomy.capacity());
    let tight = roomy.into_boxed_str().into_string();
    println!("after  {} / {}", tight.len(), tight.capacity());
}

Verified output of str_into_string.rs — regenerated by tools/run_examples.py, never hand-typed.

"hello"
"hello" capacity 5
String   24 bytes
Box<str> 16 bytes
before 5 / 64
after  5 / 5

See also

str::into_string in the standard library ↗

Po polsku

To bilet powrotny z Box<str> do String i kosztuje dokładnie zero: bajty zostają tam, gdzie były, a wartość odzyskuje jedynie pole pojemności (capacity). O to pole toczy się tu cała gra — wydruk pokazuje String jako 24 bajty, a Box<str> jako 16, więc rezygnacja z możliwości rozrastania się oszczędza osiem bajtów na każdej wartości; w strukturze trzymanej milion razy to osiem megabajtów. Warto przy okazji zapamiętać konwencję nazw, bo w Ruście jest ona umowna, ale konsekwentna: into_ to przejęcie na własność bez kopiowania, natomiast to_string z cechy (trait) ToString kopiuje tekst do świeżej alokacji — nazwy brzmią podobnie, koszt jest zupełnie inny. Skutek uboczny widać w ostatnich liniach przykładu: łańcuch znaków z zapasem 64 wraca jako 5/5, bo into_boxed_str po drodze przycina alokację do rozmiaru treści.

Szukaj po polsku: przejęcie na własność · pojemność łańcucha znaków · rust Box<str> vs String · rust into_string to_string difference