String::from_utf16¶
Level: reference · for working programmers
One line: Decodes a &[u16] of UTF-16 code units into a String, or fails — the way back from Windows, Java and JavaScript text.
Stable since 1.0.0.
The input is u16 code units, not bytes, and not characters: anything outside the Basic Multilingual Plane arrives as a surrogate pair of two units. This joins them back into one char.
It fails on an unpaired surrogate — a high surrogate with no low one after it. That is not merely theoretical: JavaScript and Windows both permit strings containing them, so text arriving from those worlds can be unrepresentable in Rust, where a String is well-formed UTF-8 by definition. from_utf16_lossy replaces them instead.
When you have bytes rather than u16s, the endianness has to come from somewhere: use from_utf16le or from_utf16be.
Example¶
string_from_utf16.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
let units: Vec<u16> = "hi 👋".encode_utf16().collect();
println!("{units:?}");
println!("{:?}", String::from_utf16(&units));
// A surrogate pair is two units for one char.
println!("{} units, {} chars", units.len(), "hi 👋".chars().count());
// An unpaired surrogate is an error, not a character.
let lone = [0xD83D];
println!("{:?}", String::from_utf16(&lone).is_err());
println!("{:?}", String::from_utf16_lossy(&lone));
// Round trip.
let text = "héllo 👋";
let wide: Vec<u16> = text.encode_utf16().collect();
println!("{}", String::from_utf16(&wide).unwrap() == text);
}
Verified output of string_from_utf16.rs — regenerated by tools/run_examples.py, never hand-typed.
See also¶
String::from_utf16_lossy— replacing unpaired surrogates instead of failingString::from_utf16le— when the input is little-endian bytesString::from_utf16be— when it is big-endian bytesstr::encode_utf16— the outbound direction
String::from_utf16 in the standard library ↗
Po polsku¶
Wejściem są jednostki kodowe u16 — nie bajty i nie znaki — a polszczyzna akurat tę różnicę skutecznie ukrywa: całe nasze „ą ć ę ł ń ó ś ź ż” mieści się w podstawowej płaszczyźnie (BMP), gdzie jedna jednostka to dokładnie jeden znak, więc złudzenie „u16 = char” trzyma się aż do pierwszego emoji. Wtedy pęka: "hi 👋" to 5 jednostek, ale 4 znaki, bo 👋 przyjeżdża jako para surogatów (surrogate pair), którą ta funkcja skleja z powrotem w jeden char. Błędem kończy się wyłącznie niesparowany surogat — Windows i JavaScript dopuszczają takie łańcuchy, a Rustowy String z definicji nie, więc tekst z tamtych światów bywa po prostu niereprezentowalny; wtedy sięgnij po from_utf16_lossy. Jeśli masz surowe bajty zamiast u16, kolejność bajtów musi skądś pochodzić — do tego są from_utf16le i from_utf16be.
Szukaj po polsku: kodowanie UTF-16 · para surogatów · jednostka kodowa · rust String::from_utf16 · rust unpaired surrogate