Skip to content

String::from_utf8_unchecked

String methods · Strings

Level: reference · for working programmers

One line: Takes a Vec<u8> as a String with no validationunsafe, and undefined behaviour if the bytes are not valid UTF-8.

pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String

Stable since 1.0.0. unsafe — the caller carries the invariant described below.

One clause: the bytes must already be valid UTF-8. The scan that from_utf8 performs is skipped entirely.

Both are O(1) in allocation terms — neither copies — so the only saving is the linear scan, which is fast. The justification therefore has to be that the bytes provably came from text: a round trip through into_bytes, or a buffer your own encoder filled.

A String holding invalid bytes is UB, not mojibake. The damage need not appear at the call site.

Example

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

fn main() {
    let s = String::from("héllo");

    // Sound: these bytes came out of a String a moment ago.
    let bytes = s.clone().into_bytes();
    let back = unsafe { String::from_utf8_unchecked(bytes) };
    println!("{back:?} identical={}", back == s);

    // The scan being skipped.
    let again = "héllo".as_bytes().to_vec();
    println!("{:?}", String::from_utf8(again));

    // What the checked version refuses.
    println!("{:?}", String::from_utf8(vec![0xff, 0xfe]).is_err());

    // Neither version copies: from_utf8 costs a scan, not an allocation.
    let big = "x".repeat(1000).into_bytes();
    let n = big.len();
    let text = String::from_utf8(big).unwrap();
    println!("{n} bytes in, {} bytes out", text.len());
}

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

"héllo" identical=true
Ok("héllo")
true
1000 bytes in, 1000 bytes out

See also

String::from_utf8_unchecked in the standard library ↗

Po polsku

Najważniejsze zdanie tej strony brzmi: String z niepoprawnymi bajtami to undefined behavior, a nie krzaczki na ekranie. To rozróżnienie gubią osoby przychodzące z C albo z Pythona, gdzie najgorszym skutkiem złego kodowania jest brzydki tekst — tutaj kompilator ma prawo zakładać, że każdy String jest poprawnym UTF-8, więc szkoda może wyjść gdziekolwiek dalej, niekoniecznie w miejscu wywołania. Warto też odebrać tej funkcji jej zwykłe usprawiedliwienie: from_utf8 również nie kopiuje — obie wersje przejmują tę samą alokację — więc oszczędza się tu wyłącznie jedno liniowe przejście po bajtach, które jest bardzo szybkie. Sięgaj po unsafe tylko wtedy, gdy da się wykazać, że bajty pochodzą z tekstu: po podróży przez into_bytes() albo z bufora wypełnionego własnym koderem.

Szukaj po polsku: niezdefiniowane zachowanie · unsafe w Ruscie · walidacja UTF-8 · rust String::from_utf8_unchecked · rust undefined behavior invalid utf8