Rustのsplit_atで日本語を使う時の注意点

O'ReillyのProgramming Rust Chapter 3: Basic TypesTuplesに出てくるsplit_atという関数について、ちょっとつまづいたところがあったのでメモ。

本題

Rustにはsplit_atという関数があり、

let value = 2;
let text = "abcde";
let (head, tail) = &text.split_at(value);
println!("{}", head);                       // => ab
println!("{}", tail);                       // => cde

という、文字列上の指定した位置で切り分け、それをタプルにして返すというものである。しかし、

let value = 2;
let text = "あいうえお";
let (head, tail) = &text.split_at(value);
println!("{}", head);
println!("{}", tail);

を実行すると、

thread 'main' panicked at 'byte index 2 is not a char boundary; it is inside 'あ' (bytes 0..3) of `あいうえお`', libcore/str/mod.rs:2108:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

と怒られてしまう。これは、'あ'はUTF8だと3バイトであり、2charの境界ではないと言っている。

結論

日本語をsplit_atするときは3の倍数の数値を使う必要があるので、

let value = 2;                              // 切り取りたい位置
let text = "あいうえお";
let (head, tail) = &text.split_at(3*value);
println!("{}", head);                       // => あい
println!("{}", tail);                       // => うえお

といった感じにする。ただし、日本語と英語が混ざったりしているときは有効でないので注意。