ごらくらいふ

プログラミングしたりゲームしたり

Zaif-api-rust v0.5.0をリリースした。trait From、エラーハンドリングに便利だった。

ついさっき、Rustで書いたzaif-apiのwrapper、v0.5.0をリリースした。

github.com

今回の改修はエラーハンドリングが目的で、「まず動く」で作っていたところを取り回しできるようにした。

活躍したのが標準ライブラリに入っている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を返してあげたいが、httpcrateが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)?)
}

参考リンク

RustでOption値やResult値を上手に扱う - Qiita : https://qiita.com/tatsuya6502/items/cd41599291e2e5f38a4a