UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【Rust】charとStringと&strについて

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を用いる

参考