str::to_uppercase¶
Level: reference · for working programmers
One line: A new String uppercased by the full Unicode rules — where a single character can become two, so ß becomes SS.
Stable since 1.2.0.
The famous case is German ß: its uppercase is SS, two characters. So uppercasing can change both the byte length and the character count, and s.to_uppercase().chars().count() is not s.chars().count().
That makes uppercasing not round-trippable: "ß".to_uppercase().to_lowercase() is "ss", not "ß". Any code that uppercases for display and lowercases to compare will silently merge distinct inputs.
Ligatures behave the same way — fi uppercases to FI.
As with lowercasing, there is no locale: the Turkish dotted/dotless distinction is not applied.
Example¶
str_to_uppercase.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
println!("{:?}", "Hello".to_uppercase());
// One character becomes two.
let sharp_s = "ß";
println!("{:?} -> {:?}", sharp_s, sharp_s.to_uppercase());
println!("{} char -> {} chars", sharp_s.chars().count(), sharp_s.to_uppercase().chars().count());
// So it does not round-trip.
println!("{:?}", "ß".to_uppercase().to_lowercase());
println!("round trips: {}", "ß".to_uppercase().to_lowercase() == "ß");
// Ligatures expand too.
println!("{:?}", "\u{FB01}".to_uppercase()); // LATIN SMALL LIGATURE FI
// A whole word. Here the BYTE count happens to match -- 'ß' is two bytes
// and "SS" is two bytes -- while the CHARACTER count still grows.
let word = "straße";
let upper = word.to_uppercase();
println!("{word:?} {} bytes / {} chars", word.len(), word.chars().count());
println!("{upper:?} {} bytes / {} chars", upper.len(), upper.chars().count());
}
Verified output of str_to_uppercase.rs — regenerated by tools/run_examples.py, never hand-typed.
"HELLO"
"ß" -> "SS"
1 char -> 2 chars
"ss"
round trips: false
"FI"
"straße" 7 bytes / 6 chars
"STRASSE" 7 bytes / 7 chars
See also¶
str::to_lowercase— the other directionstr::to_ascii_uppercase— the ASCII-only version, which is length-preservingstr::make_ascii_uppercase— in place, no allocationstr::chars— why the character count can change
str::to_uppercase in the standard library ↗
Po polsku¶
Po polsku żadna litera przy zamianie na wielką nie rośnie — ą → Ą, ż → Ż, jeden znak na jeden — i właśnie dlatego tak łatwo wyrobić sobie tu fałszywe przekonanie, że to_uppercase zachowuje długość. Wystarczy jedno niemieckie ß albo ligatura fi wklejona z PDF-u, żeby liczba znaków urosła: "ß" to jeden znak, "SS" już dwa, a "straße" ma 6 znaków wobec 7 w "STRASSE" — przy identycznej liczbie bajtów, co myli podwójnie. Praktyczny wniosek jest taki, że zamiana na wielkie litery nie jest odwracalna: "ß".to_uppercase().to_lowercase() daje "ss", więc schemat „wyświetlam wielkimi, porównuję małymi” po cichu skleja ze sobą dane, które były różne.
Szukaj po polsku: wielkie litery a długość łańcucha · liczba znaków a liczba bajtów · rust to_uppercase ß SS · rust uppercase is not reversible