Skip to content

str::is_ascii

str methods · Strings

Level: reference · for working programmers

One line: true if every byte is below 128 — the precondition the whole ascii family is asking about.

pub const fn is_ascii(&self) -> bool

Stable since 1.23.0. Usable in a const context.

A linear scan, const, and cheap because it needs no decoding: valid UTF-8 is ASCII exactly when no byte has its high bit set.

Its value is as a guard. to_ascii_lowercase, eq_ignore_ascii_case, trim_ascii and split_ascii_whitespace are all correct-and-fast on ASCII and quietly wrong on anything else — this is how you find out which you have before choosing.

It is also the fastest way to know that byte length equals character length: for ASCII, len() and chars().count() agree, and every byte offset is a character boundary.

Example

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

fn main() {
    for s in ["hello", "héllo", "", "123!@#"] {
        println!("{:<8} ascii={}", format!("{s:?}"), s.is_ascii());
    }

    // The guard that picks the right family.
    for s in ["Content-Type", "Größe"] {
        let lowered = if s.is_ascii() { s.to_ascii_lowercase() } else { s.to_lowercase() };
        println!("{:<14} -> {lowered:?}", format!("{s:?}"));
    }

    // For ASCII, the two rulers agree and every offset is a boundary.
    let a = "hello";
    println!("{} {} {}", a.len(), a.chars().count(),
             (0..=a.len()).all(|i| a.is_char_boundary(i)));

    // const.
    const TOKEN: &str = "GET";
    const OK: bool = TOKEN.is_ascii();
    println!("{OK}");
}

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

"hello"  ascii=true
"héllo"  ascii=false
""       ascii=true
"123!@#" ascii=true
"Content-Type" -> "content-type"
"Größe"        -> "größe"
5 5 true
true

See also

str::is_ascii in the standard library ↗

Po polsku

Dla polskiego tekstu ta metoda zwraca false prawie zawsze — i właśnie dlatego jest przydatna: „Gdańsk” czy „Łódź” zawierają bajty powyżej 127, więc cała rodzina *_ascii (to_ascii_lowercase, eq_ignore_ascii_case, trim_ascii, split_ascii_whitespace) zostawi te litery nietknięte. Nie zgłosi przy tym żadnego błędu, po prostu przepuści „Ł” bez zmiany, a to najbardziej podstępny rodzaj pomyłki, bo testy na słowie „hello” przechodzą bez zarzutu. Stąd wzorzec z przykładu: if s.is_ascii() { s.to_ascii_lowercase() } else { s.to_lowercase() } — szybka ścieżka tam, gdzie wolno, poprawna wszędzie indziej. Drugi zysk jest taki, że is_ascii() równe true gwarantuje, że len() w bajtach zgadza się z liczbą znaków i każde przesunięcie jest granicą znaku — czego przy polskich literach nie wolno założyć nigdy.

Szukaj po polsku: polskie znaki diakrytyczne w Ruscie · ASCII a UTF-8 · rust is_ascii to_ascii_lowercase · rust to_lowercase unicode