Skip to content

str::ceil_char_boundary

str methods · Strings

Level: reference · for working programmers

One line: The nearest character boundary at or above a byte offset — rounds up, so the result can exceed the offset you asked for.

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

Stable since 1.91.0. Usable in a const context.

The complement of floor_char_boundary. Where floor never exceeds the requested offset, ceil never falls short of it — by up to three bytes, since that is the widest a UTF-8 character can be.

That makes ceil the wrong choice for a hard byte budget and the right choice when the offset marks the start of something you must not cut into: skipping a header of at least n bytes, or resuming a scan at or after a known position.

It panics if the offset is past the end, unlike floor, which clamps. There is no boundary above len() to return, so the asymmetry is forced.

Example

str_ceil_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, 11] {
        let cut = s.ceil_char_boundary(n);
        println!("offset {n:>2} -> {cut:>2}  rest {:?}", &s[cut..]);
    }

    // Never below the request; floor is never above it.
    for n in [2, 8] {
        println!("n={n}: floor {} ceil {}", s.floor_char_boundary(n), s.ceil_char_boundary(n));
    }

    // At most three bytes of overshoot, since that is the widest character here.
    let wide = "a\u{1F600}b";                 // 'a', a 4-byte emoji, 'b'
    for n in 1..=5 {
        println!("wide n={n} -> {}", wide.ceil_char_boundary(n));
    }

    // len() is a boundary; beyond it there is none, which is why ceil panics
    // there while floor clamps.
    println!("{} {}", s.ceil_char_boundary(s.len()), s.floor_char_boundary(999));
}

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

offset  0 ->  0  rest "héllo wörld"
offset  1 ->  1  rest "éllo wörld"
offset  2 ->  3  rest "llo wörld"
offset  3 ->  3  rest "llo wörld"
offset  7 ->  7  rest "wörld"
offset  8 ->  8  rest "örld"
offset 11 -> 11  rest "ld"
n=2: floor 1 ceil 3
n=8: floor 8 ceil 8
wide n=1 -> 1
wide n=2 -> 5
wide n=3 -> 5
wide n=4 -> 5
wide n=5 -> 5
13 13

See also

str::ceil_char_boundary in the standard library ↗

Po polsku

ceil_char_boundary zaokrągla w górę do najbliższej granicy znaku (char boundary), więc potrafi oddać offset większy niż ten, o który prosisz — o jeden bajt przy polskiej literze diakrytycznej, o trzy przy emoji. To rozstrzyga, kiedy go używać: przy twardym limicie bajtów (kolumna w bazie, ramka protokołu) potrzebujesz floor_char_boundary, bo ceil ten limit przekroczy; ceil pasuje wtedy, gdy offset wyznacza początek czegoś, czego nie wolno naciąć — pomijasz nagłówek o długości co najmniej n bajtów albo wznawiasz skanowanie od pozycji nie wcześniejszej niż znana. Jest jeszcze asymetria warta zapamiętania: dla offsetu spoza łańcucha floor przycina wynik do len(), a ceil panikuje, bo powyżej len() żadnej granicy już nie ma.

Szukaj po polsku: granica znaku w UTF-8 · zaokrąglanie do granicy znaku · bezpieczne przycinanie łańcucha · rust ceil_char_boundary · rust byte index is not a char boundary