RustのcharとStringと&strについて
char型
char型の場合は「'」シングルクォートを用いる
この辺はJavaと一緒なのですんなり理解できる
charは0x0000から0xD7FFまで、もしくは0xE000から0x10FFFFまでのUnicodeポイントを保持する
つまり、Unicode Scalar Values(USV)が保証されている
USVは以前調べた uga-box.hatenablog.com
Unicdeのコードポイントを16進数でこんな感じで書ける
'\u{HHHHHH}'
String型
ダブルクォートで囲む
改行した場合、改行されたまま表示される
println!("In the room the women come and go, Singing of Mount Abora");
改行させたくない場合は、バックスラッシュをつけると改行文字と次の行の冒頭の空白文字が削除される
println!("In the room the women come and go, \ Singing of Mount Abora");
こういう記法もある
println!(r###" This raw string started with 'r###'. Therefore it does not end until we reach a quota mark ('"') followed immediately by three sings ('###'): "###);
Stringは文字を可変幅のエンコーディングであるUTF-8バイト配列で保持するので、サイズ可変なバッファをもっている
バッファはヒープに確保され、必要に応じてサイズを変更することができる
well-formed UTF-8であることが保証されているので、Vec<u8>
と考えることができる
保証されているかの確認で試しに以下を実行してみたら
let s = &"𠮷野家"[1..]; println!("{}", s);
次のようなエラーが発生した
byte index 1 is not a char boundary; it is inside '𠮷' (bytes 0..4) of `𠮷野家`
&str
&str(「stir」もしくは「string slice」と読む)は何か別のものが「所有」している連続したUTF-8への参照で「借用」しているもの
例えば、下のoodles
が&str
で、noodles
の最後の6バイトを参照していることになる
let noodles = "noodles".to_string(); // String let oodles = $noodles[1..]; // &str
どちらを使うのかは後日調べる
文字列比較
==
と!=
をサポートする
Javaと違うのはメモリ上同じ場所を指していなくてもよいので、同じ文字を順番にもっていれば同じだと判断される
assert!("ONE".to_lowercase() == "one");
<
などの比較演算子は文字コードポイントを用いた辞書順に比較する
contains
, replace
, trim
などのよく使いそうなものもだいたいある
ill-formed UTF-8の扱い
Rustはwell-formed UTF-8であることが保証されているが、外部連携で有効でないUnicodeを扱わなければならい場合がある
この場合は、いくつかの文字列に似た形を提供する
- UnicodeテキストについてはStringと&strを用いる
- ファイル名に含まれていたら
std::path::PathBuf
と&Path
を用いる(後日調べる - 文字データではないバイナリーデータの場合は
Vec<u8>
と&[u8]
を用いる - 環境変数名などのOSにネイティブな形で提供される場合は
OsString
と&OsStr
を用いる(後日調べる - null文字を終端としているCライブラリと連携する場合は
std::ffi::CString
と&CStr
を用いる