このページでは Rust のファイル操作処理の引数を理解するために AsRef<T> についてまとめる。

AsRef<T>

AsRef<T> というトレイトを実装した型からは as_ref&T を借用できる。

convert/mod.rs
pub trait AsRef<T: ?Sized> {
  fn as_ref(&self) -> &T;
}

たとえば StringAsRef<str>AsRef<Path> を実装している。

let str: &str = string.as_ref();
let path: &Path = string.as_ref();

AsRef<T> を実装する型

AsRef<Path>String, str, OsString, OsStr, PathBuf そして Path などが実装している。

そのためこの Book で取り上げた 6 つの型は全て as_ref&Path として借用できる。

let path: &Path = string.as_ref();
let path: &Path = str.as_ref();
let path: &Path = os_string.as_ref();
let path: &Path = os_str.as_ref();
let path: &Path = path_buf.as_ref();
let path: &Path = path.as_ref();

Rust のファイル操作処理の引数

Rust のファイル操作処理の引数は AsRef<Path> になっている。

たとえば指定されたパスを File として取得する open の引数は AsRef<Path> だ。

fs.rs
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
    OpenOptions::new().read(true).open(path.as_ref())
}

つまり open の引数はこの Book で整理した 6 つの型のどれでも構わないということになる。

let file = std::fs::File::open(string);
let file = std::fs::File::open(str);
let file = std::fs::File::open(os_string);
let file = std::fs::File::open(os_str);
let file = std::fs::File::open(path_buf);
let file = std::fs::File::open(path);

ほかにもたとえば、前のページでとりあげた join の引数も AsRef<Path> なので、引数は &str でなくても構わない。

自分でパスを扱う処理を作るときも同じようにすると次のような利点があるので、覚えておくといいだろう。

  • 標準ライブラリと親和性がいい
  • 汎用的に使える処理になる
  • テストのときは "/test/app.log" みたいに &str がそのまま渡せて楽

整理

  • AsRef<T> というトレイトを実装した型からは as_ref&T を借用できる
  • AsRef<T>String, str, OsString, OsStr, PathBuf, Path などが実装している
  • Rust のファイル操作処理の引数は AsRef<Path> になっている

参考

https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/borrow-and-asref.html