Skip to content

str::floor_char_boundary

str methods · Strings

Level: reference · for working programmers

One line: The nearest character boundary at or below a byte offset — the safe way to truncate to a byte budget.

pub const fn floor_char_boundary(&self, index: usize) -> usize

Stable since 1.91.0. Usable in a const context.

Truncating to a fixed number of bytes is a real requirement — a database column, a protocol field, a fixed-width display — and the naive &s[..n] panics on any input whose nth byte is mid-character. This gives you the largest legal endpoint that does not exceed n, so the result always fits the budget.

An offset past the end is clamped to len(), so it never panics and never returns something out of range.

Pair it with ceil_char_boundary, which rounds the other way and can therefore exceed the budget by up to three bytes — which is why floor is the one for a hard limit.

Note the budget is in bytes. To truncate to a number of characters, take from char_indices instead.

Example

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

fn main() {
    let s = "héllo wörld";

    for n in [0, 1, 2, 3, 7, 8, 99] {
        let cut = s.floor_char_boundary(n);
        println!("budget {n:>2} -> cut {cut:>2}  {:?}", &s[..cut]);
    }

    // The naive version panics on exactly the offsets floor repairs.
    println!("boundary at 2? {}", s.is_char_boundary(2));

    // Always within budget, which ceil cannot promise.
    for n in [2, 8] {
        println!("n={n}: floor {} <= n, ceil {} >= n",
                 s.floor_char_boundary(n), s.ceil_char_boundary(n));
    }

    // A byte budget is not a character budget.
    let by_chars: String = s.chars().take(5).collect();
    println!("5 chars = {by_chars:?} ({} bytes)", by_chars.len());
}

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

budget  0 -> cut  0  ""
budget  1 -> cut  1  "h"
budget  2 -> cut  1  "h"
budget  3 -> cut  3  "hé"
budget  7 -> cut  7  "héllo "
budget  8 -> cut  8  "héllo w"
budget 99 -> cut 13  "héllo wörld"
boundary at 2? false
n=2: floor 1 <= n, ceil 3 >= n
n=8: floor 8 <= n, ceil 8 >= n
5 chars = "héllo" (6 bytes)

See also

str::floor_char_boundary in the standard library ↗

Po polsku

Ta metoda odpowiada na pytanie, które przy polskim tekście wraca bez przerwy: jak przyciąć łańcuch znaków do limitu bajtów, nie rozcinając znaku. Limit bajtowy jest zupełnie realny — kolumna w bazie, pole protokołu, ograniczenie w API — a naiwne &s[..n] panikuje dokładnie wtedy, gdy n-ty bajt wypada w środku litery, czyli w polskim tekście bardzo często, bo każda z liter ą ć ę ł ń ó ś ź ż zajmuje dwa bajty. floor_char_boundary cofa przesunięcie do najbliższej legalnej granicy, więc wynik zawsze mieści się w budżecie — widać to w tabeli powyżej: budżet 2 daje cięcie na 1, bo bajt 2 stoi w środku é. Przesunięcie za końcem łańcucha jest przycinane do len(), więc ta metoda nie panikuje nigdy.

Bliźniacze ceil_char_boundary zaokrągla w drugą stronę i potrafi przekroczyć budżet nawet o trzy bajty, więc przy twardym limicie bierze się floor, a ceil tylko wtedy, gdy limit wolno lekko przekroczyć. I rozróżnienie najważniejsze: budżet jest bajtowy, a nie znakowy — przycięcie do dziesięciu znaków to zupełnie inne zadanie i robi się je przez chars().take(10) albo char_indices(). Metoda jest przy tym świeża (stabilna od 1.91.0), więc starsze polskie materiały jej nie znają i pokazują ręczną pętlę while !s.is_char_boundary(n) { n -= 1 } — daje ten sam wynik, tylko dłuższą drogą.

Szukaj po polsku: przycinanie łańcucha do bajtów · granica znaku UTF-8 · rust floor_char_boundary · rust byte index is not a char boundary · rust truncate string bytes