anyhowを使ってエラーの型に応じた処理を書く

rustのanyhowを使って、エラーの型に応じた処理を書く方法が分からなかったのでメモ。

以下の★のところで処理を記述している。

use anyhow::{Context, Result};

fn get_int() -> Result<i32> {
  let path  = "test.txt";
  let num_s = std::fs::read_to_string(path)
    .map(|s| s.trim().to_string())
    .with_context(|| format!("failed to read string from {}", path))?;
  num_s
    .parse::<i32>()
    .with_context(|| format!("failed to parse string '{}'", num_s))
}

fn main() {
  match get_int() {
    Ok(x)  => println!("{}", x),
    Err(e) => {
      println!("{}", e);
      if let Some(error) = e.downcast_ref::<std::num::ParseIntError>() {
        // ★ std::num::ParseIntErrorが発生したときの処理
        println!("Parse Error {:#?}", error);
      } else if let Some(error) = e.downcast_ref::<std::io::Error>() {
        // ★ std::io::Errorが発生したときの処理
        println!("I/O Error {:#?}", error);
      } else {
        println!("Other Error");
      }
    },
  }
}