My Awesome Rust: thiserror
Page content
Rustで独自のエラーを自作する際に以下のようなやらないといけないことが多くあり、面倒です。
std::error::Errortraitを実装- 読みやすいエラーログを作るために
Displaytraitを実装 - 他のエラーなどからの変換を容易にするために
From<T>traitを実装
また、エラーは構造体だったり、列挙型だと便利であることが多いです。 thiserror (https://docs.rs/thiserror/latest/thiserror/)はこうしたエラーの自作を便利にするライブラリです。
使い方
thiserror はCargo.tomlに依存として追加することで使えるようになります。
[dependencies]
thiserror = "1"
以下はドキュメント(https://docs.rs/thiserror/latest/thiserror/)にある実装例の一つです。
use thiserror::Error;
#[derive(Error, Debug)]
pub enum DataStoreError {
#[error("data store disconnected")]
Disconnect(#[from] io::Error),
#[error("the data for key `{0}` is not available")]
Redaction(String),
#[error("invalid header (expected {expected:?}, found {found:?})")]
InvalidHeader {
expected: String,
found: String,
},
#[error("unknown data store error")]
Unknown,
}
Disconnectではerrorという属性でDisplayトレイトを"data store disconnected"というエラーメッセージで実装しています。また、io::Errorに対するFromトレイトを実装しています。- Redactionでは
errorという属性でDisplayトレイトを実装する際にタプルの値を利用しています。#[error("{0}")] ⟶ write!("{}", self.0)という意味なので、0番目の値のDisplayトレイトの実装を呼び出しています。 - InvalidHeaderでは、
expectedとfoundのDebugトレイトの実装を呼び出してエラーメッセージを作成しています。#[error("{var:?}")] ⟶ write!("{:?}", self.var)という意味を表しています。
エラーをラップしていくためにsourceやbacktraceといった属性が用意されていますが、個人的にはanyhowを使えば良い気がしています。