Using anyhow
and my favorite color-eyre
crates for error reporting and handling.
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
#[derive(Error, Debug)]
pub struct MyError {
msg: String,
#[source] // optional if field name is `source`
source: eyre::Error,
}
Using anyhow
(we prefer color-eyre)
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
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
// 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);
}
Top comments (0)