ついさっき、Rustで書いたzaif-apiのwrapper、v0.5.0をリリースした。
今回の改修はエラーハンドリングが目的で、「まず動く」で作っていたところを取り回しできるようにした。
活躍したのが標準ライブラリに入っているFrom<T>
トレイトで、あるstructがこれを実装するということは、特定の型から変換できると宣言することになる。
fn dl_and_parse (loader: http::Downloader, parser: parse::Parser) -> Result<Parsed, parse::Error> { // ダウンロード処理 let text = downloader.fetch().unwrap().text().unwrap(); // パースして返す parser.from_text(text) }
まず動くものとしてこういうものを書いた。
これだと、downloader.fetch()
で問題があった場合などにpanic
を起こしてしまう。
落ちないようにErr
を返してあげたいが、http
crateがparse
のErrorを持っていないので、単純にunwrapを?
に書き換えただけではコンパイルエラーになってしまう。
これを解決するのが、Fromトレイト。 これを実装することで異なる型に馴染むことができる。
とはいえ、よそのcrateのErrorをまた別のcrateのErrorに差し込むのは流石に行儀が悪いので、Enumを用意して各crateのerrorを包むだけにした。 (それに、自分で丁寧なエラーハンドリングをしなくて良いので。)
enum MyError { HttpError(http::Error), ParseError(parse::Error), } impl From<http::Error> for Error { fn from(err: http::Error) -> Self { Error::HttpError(err) } } impl From<parse::Error> for Error { fn from(err: parse::Error) -> Self { Error::ParserError(err) } }
これにより、unwrap()
を排除しつつ、panicを起こさずに異常を伝えられるようになった。
fn dl_and_parse (loader: http::Downloader, parser: parse::Parser) -> Result<Parsed, MyError> { // ダウンロード処理 let text = downloader.fetch()?.text()?; // パースして返す Ok(parser.from_text(text)?) }
trait From「彼なら、僕になれる」
— 華夜 (@Yajamon) 2018年3月2日
trait Into「僕なら、彼になれる」#rust #rustlang
参考リンク
RustでOption値やResult値を上手に扱う - Qiita : https://qiita.com/tatsuya6502/items/cd41599291e2e5f38a4a