Error handling (Part 2)
Tags: rust, beginners
Published: 2021-11-27 05:12:28

Using `anyhow` and my favorite `color-eyre` crates for error reporting and handling.

``` rust
use color_eyre::eyre::{eyre, Result};
use color_eyre::*;
		  
fn main() -> Result<()> {
	color_eyre::install().unwrap();
		  
		  
// ************************************************************
  	// ******************** wrap_err
// ************************************************************
  	// wrap_err wraps the error with new message
let _a = "123a".parse::<f32>().wrap_err("parsing something bad")?;
/*
Error:
    0: parsing something bad
    1: invalid float literal
		  
Location:
    src/main.rs:25
*/
		  
		  
//************************************************************
// ******************** eyre!("message")
//************************************************************
// eyre! just changes the underlying error message and colors it
/*
Error:
    0: parsing something bad
		  
Location:
    src/main.rs:23
		  
*/
let _a = "123a"
   .parse::<f32>()
   .map_err(|_e| eyre!("parsing something bad"))?;
		  
		  
// ************************************************************
  	// ******************** eyre!(Error)
// ************************************************************
// bubble up underlying error, not helpful, until you have RUST_BACKTRACE
/*
Error:
    0: invalid digit found in string
		  
Location:
    /rustc/a178d0322ce20e33eac124758e837cbd80a6f633/library/core/src/convert/mod.rs:538
*/
		  
let _a = "123a"
   .parse::<f32>()
   .map_err(|e| eyre!(e))?;
		  
	Ok(())
}
		  
```
If using `thiserror` for creating error types and propagating color-eyre errors to them, use
``` rust
#[derive(Error, Debug)]
pub struct MyError {
    msg: String,
    #[source]  // optional if field name is `source`
    source: eyre::Error,
}
```
Using `anyhow` (we prefer color-eyre)
``` rust
use anyhow::*;
use std::fmt::Debug; // 1.0.40

fn test_error1() -> Result<()> {
    let _ = "a".parse::<i32>().context("some context with parse i32")?;
    let _ = "a".parse::<f64>()?;
    Ok(())
}

fn test_error2() -> Result<()> {
    let _ = "1".parse::<i32>()?;
    let _ = "a".parse::<f64>()?;
    Ok(())
}

fn main() -> Result<()> {
    test_error1().context("give some context to the error generated from this error")?;
    Ok(())
}

```

## Using `anyhow` and `thiserror` together
``` rust
use anyhow::*;
use std::fmt::Debug;
use std::num::{ParseFloatError, ParseIntError};
use thiserror; // 1.0.25 // 1.0.40

#[derive(thiserror::Error, Debug)]
enum MyErrors {
    #[error("my first error")]
    Error1(#[from] ParseIntError),
    #[error("my second error")]
    Error2(#[from] ParseFloatError),
}

fn test_error1() -> Result<(), MyErrors> {
    let _ = "a".parse::<i32>()?; ///// raises error with error message "my first error"
    let _ = "a".parse::<f64>()?;
    Ok(())
}

fn test_error2() -> Result<()> {
    let _ = "1".parse::<i32>()?;
    let _ = "a".parse::<f64>()?;
    Ok(())
}

fn main() -> Result<()> {
    // test_error1()?;
    if let Err(e) = test_error1() {
        println!("Error message: {}", e);
        //        if let Some(source) = e.source() { ///// this is error because source is not found, remove this block
        //            println!(" Caused by: {}", source)
        //        }
    }
    // if let Err(e) = test_error2() {
    //     println!("Error message: {}", e)
    // }
    Ok(())
}

////// Error message: my first error
```

### Simple anyhow macro

```rust
// simple macro
use anyhow::{anyhow, Error};

macro_rules! test {
    ($x:expr) => { $x.map_err(|e| anyhow!(e)) }
}



// Extension method - this is good
use anyhow::{anyhow, Error};
trait AnyhowExt<O, E> {
    fn as_anyhow(self) -> Result<O, Error>;
}

impl<O, E> AnyhowExt<O, E> for Result<O, E> where E: Into<Error> {
    fn as_anyhow(self) -> Result<O, Error> {
        self.map_err(|e| anyhow!(e))
    }
}

fn main() {
    use AnyhowExt;
    let err = "NaN".parse::<u32>();
    //let y: Result<u32, Error> = err.map_err(|e| anyhow!(e));
    let y: Result<u32, Error> = err.as_anyhow();
    println!("{:?}", y);
}
```