Crate n0_error

Source
Expand description

§n0-error

An error library that supports tracking the call-site location of errors.

This crate provides a trait and proc macro to ergonomically work with enum or struct errors. The macro can add a meta field to structs and enum variants, which stores the call-site location of errors. The StackError trait provides access to this metadata for both the current error, and all its sources, as long as they also implement StackError.

Additionally, this crate provides an anyhow-style AnyError type, which is a type-erased container for either StackError or std::error::Error errors.

use n0_error::{e, stack_error, StackError, Result, StackResultExt, StdResultExt};

/// The `stack_error` macro controls how to turn our enum into a `StackError`.
///
/// * `add_meta` adds a field to all variants to track the call-site error location
/// * `derive` adds `#[derive(StackError)]`
/// * `from_sources` creates `From` impls for the error sources
#[stack_error(derive, add_meta, from_sources)]
enum MyError {
    /// We can define the error message with the `error` attribute
    #[error("bad input ({count})")]
    BadInput { count: usize },
    /// Or we can define a variant as `transparent`, which forwards the Display impl to the error source
    #[error(transparent)]
    Io {
        /// For sources that do not implement `StackError`, we have to mark the source as `std_err`.
        #[error(std_err)]
        source: std::io::Error,
    },
}

// A function that returns a std::io::Error
fn fail_io() -> std::io::Result<()> {
    Err(std::io::Error::other("io failed"))
}

// An outer function returning our custom MyError
fn some_fn(count: usize) -> Result<(), MyError> {
    if count == 13 {
        // The `e` macro constructs a `StackError` while automatically adding the `meta` field.
        return Err(e!(MyError::BadInput { count }));
    }
    // We have a `From` impl for `std::io::Error` on our error.
    fail_io()?;
    // Without the From impl, we'd need to forward the error manually.
    // The `e` macro can assist here, so that we don't have to declare the `meta` field manually.
    fail_io().map_err(|source| e!(MyError::Io, source))?;
    Ok(())
}

// A main function that returns AnyError (via the crate's Result alias)
fn run() -> Result<()> {
    // We can add context to errors via the result extensions.
    // The `context` function adds context to any `StackError`.
    some_fn(13).context("failed at some_fn")?;
    // To add context to std errors, we have to use `std_context` from `StdResultExt`.
    fail_io().std_context("failed at fail_io")?;
    Ok(())
}

fn main() -> Result<()> {
    let err = run().unwrap_err();
    assert_eq!(
        format!("{err:#}"),
        "failed at some_fn: bad input (13)"
    );
    Ok(())
}

/// You can also use the macros with tuple structs or enums.
/// In this case the meta field will be added as the last field.
#[stack_error(derive, add_meta)]
#[error("tuple fail ({_0})")]
struct TupleStruct(u32);

#[stack_error(derive, add_meta)]
enum TupleEnum {
    #[error("io failed")]
    Io(#[error(source, std_err)] std::io::Error),
}

Macros§

  • Converts a value into AnyError.
  • Returns an error result by constructing a StackError with e.
  • Returns an error result by constructing an AnyError with anyerr.
  • Constructs an error enum/struct value while automatically filling meta: Meta.
  • Ensures a condition, otherwise returns the error constructed with e from the remaining args.
  • Ensures a condition, otherwise returns an AnyError.
  • Unwraps a result, returning in the error case while converting the error.
  • Unwraps a result, returning in the error case while adding context to the error.

Structs§

Enums§

  • Reference to an error which can either be a std error or a stack error.
  • Output style for rendering error sources in a Report.

Traits§

Functions§

  • Returns a result with the error type set to AnyError.
  • Creates new Meta capturing the caller location.

Type Aliases§

Attribute Macros§

Derive Macros§

  • Derive macro that implements StackError, Display, Debug, std::error::Error, and generates From<T> impls for fields/variants configured via #[error(..)].