Crate debug_err

Crate debug_err 

Source
Expand description

An error handling library with under 50 lines of code and no dependencies, that keeps track of the source location of every error. DebugErr identifies the crate name, file name and line number of every error event.

§The Basics

To build an error:

use debug_err::{DebugErr, src};

pub fn divide(num: f32, denom: f32) -> Result<f32, DebugErr> {
    if denom == 0.0 { Err(src!("Denominator must not be zero.")) }
    Ok(num / denom)
}

§Coercing other error types to DebugErr

This extracts the message from another error type

use debug_err::{DebugErr, src};

let num: f32 = "abc".parse().map_err(|e| src!("Failed to parse with error '{e}'"))?;

§Coercing DebugErr to other error types.

The cleanest method is just to directly use DebugErr in your library, and construct and return errors of this type, but if you still need to build your own error types then,

use {
    debug_err::{DebugErr, src},
    std::fmt,
};

#[derive(Clone, Debug)]
pub struct OwnError(DebugErr);

// Uses ``DebugErr``'s ``Display`` implementation.
impl fmt::Display for OwnError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

// This is used to coerce ``DebugErr`` into one's own type using the ``?`` operator,
// so that ``DebugErr`` doesn't have to be coerced explicitly.
impl From<DebugErr> for OwnError {
    fn from(debug: DebugErr) -> Self { OwnError(debug) }
}

// and then at the error construction site,

type Result<T> = std::result::Result<T, OwnError>;

pub fn divide(num: f32, denom: f32) -> Result<f32> {
    if denom == 0.0 { return Err(src!("Denominator must not be zero."))? }
    Ok(num / denom)
}

pub fn parse(num: &str) -> Result<f32> {
    let f: f32 = num.parse().map_err(|e| src!("Failed to parse '{num}' with error: {e}"))?;
    Ok(f)
}

Macros§

src
Create a DebugErr type, which includes information about the locations of the error.

Structs§

DebugErr
Use the src!() macro to build this error.