前回の記事の疑問点などに対してκeenさんにPRでとても丁寧に教えていただいた

エラーハンドリング

エラーハンドリングは通常Error型に対するパターンマッチで行います。
ただ、そのためにはBox<Error>のようにトレイトで隠蔽してしまうとハンドリング出来なくなるので
io::Errorなど具体的な型を使う必要がありす。
ただ、今回はProtobufErrorがio::Errorから変換出来るので具体的に扱えそうですね。
サンプルコードくらいでわざわざカッチり管理するのが面倒な時は`()`や`String`が`Error`を実装しているのでそれでどうにかするというのも手です。

因みにpanicからのrecoverはかなりの特殊用途向けなので基本的に使ってはいけません。
ブログでの疑問点についてコメント #1
なるほど。
今回の場合、事前にファイルの存在チェックを行わずにError型のパターンマッチで判定するにはこんな感じだろうか。
let path = Path::new(file_path);
match File::open(&path) {
    Ok(file) => {
        let mut br = BufReader::new(file);
        let mut cis = CodedInputStream::from_buffered_reader(&mut br);
        address.merge_from(&mut cis)?;
    },
    Err(e) => match e.kind() {
        io::ErrorKind::NotFound => (),
        _ => return Err(ProtobufError::IoError(e)),
    }
}

また、map_err(ProtobufError::IoError)を呼ぶようにしている箇所は
io::Error -> ProtobufErrorに変換するため各所にこのような行があります。
あまり ProtobufErrorの実装が良くない(本来ならFrom<io::Error>を実装すべき)のでこうなってます。
ブログでの疑問点についてコメント #1
との事だったが、rust-protobufリポジトリの方にPRが出ているようだ。

String -> &strの明示的な変換

AsRef::as_refはメソッドとして(第一引数がselfとして)定義されているので
String::as_ref(&args[1])よりもargs[1].as_ref()が好ましいというか正しい書き方です。
(以下略)
ブログでの疑問点についてコメント #1
いくつか変換方法があるそうだが、今回はargs[1].as_ref()に変更してみた。

File::openで作ったファイルに書き込んでもエラーにならない?

ここからの一連のコメントRustといえどリソースの解放は注意に詳しいが、
BufWriterDropのタイミングで発生したエラーが無視されてこのような現象になったようだ。
そもそもCodeOutputStreamがバッファリングしているためBufWriterを使う必要が無かったので
File::create(&path)で生成したstd::fs::FileCodeOutputStreamに渡すようにしてみた。

κeenさん、ありがとうございました。

Copyright© 2011-2021 Shunsuke Otani All Right Reserved .