Skip to content

str::to_uppercase

str methods · Strings

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.

pub fn to_uppercase(&self) -> String

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 — 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_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 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