[][src]Crate error_context

This crate provides methods and types that help with adding additional context information to error types.

Usage

There are two ways to add context information to your error types:

  1. by extending your error type with a filed that will store the context information and then adding context to the error value,
  2. wrapping any error type together with the context information and then converting this boundle to type that can store the error and context.

This crate provides types, traits and extension methods designed to help with the above tasks. It is recommended to import all the types and traits via perlude module: use error_type::prelude::*.

Adding context to types that can collect context

If your type can collect context information you can implement WithContext trait for it. By doing so you enable some of the provided extension methods to work with your type.

Directly to value

You can add context to value of your error with .with_context(context).

To error wrapped in Result

Use .error_while(context) method on Result value to add context to error value of type that implements WithContext.

You can also use in_context_of(context, closure) function to add context to result of provided closure. You can use ? within the closure to control the flow.

There is also .error_while_with(context_function) and in_context_of_with(context_function, closure) variants that can be used to defer construction of context to error path.

Adding context to other types

External error types may not support adding context. The ErrorContext type can be used to wrap error value and context information together. This type implements WithContext and adding further context information will result in wrapping with another layer of ErrorContext type.

The main use case for this method is to wrap error in one or more layers of context and then convert them to your own error type consuming the error and the context information using From trait. This enables use of ? to convert external error types with added context to your error type.

Directly to value

You can wrap any type in ErrorContext type using .wrap_context(context) method.

To error wrapped in Result

When working with Result value you can wrap error value in ErrorContext using .wrap_error_while(context).

There is also .wrap_error_while_with(context_function) and wrap_in_context_of_with(context_function, closure) variants that can be used to defer construction of context to error path.

Using ErrorNoContext

You can also use .to_root_cause() directly on error value or .map_error_context() on Result to wrap error type in ErrorNoContext.

Adding context information to ErrorNoContext converts it into ErrorContext. ErrorNoContext is intended to be used within function scope to enable functions and methods that work with WithContext to add context information bafore error is returned.

Usage example

In this example we will create our own error type called MyError. We will wrap extra context information to std::io::Error value using .wrap_error_while(context) and as another example using .wrap_in_context_of(context, closure). Finally by implementing From<ErrorContext<io::Error, &'static str>> for MyError we can use ? operator to convert this error to MyError persisting the context information added.

use error_context::prelude::*;
use std::io;

enum MyError {
    IoError(io::Error, &'static str),
}

impl From<ErrorContext<io::Error, &'static str>> for MyError {
    fn from(error: ErrorContext<io::Error, &'static str>) -> MyError {
        MyError::IoError(error.error, error.context)
    }
}

fn work_with_file() -> Result<(), MyError> {
    Err(io::Error::new(io::ErrorKind::InvalidInput, "boom!"))
        .wrap_error_while("working with file")?;
    Ok(())
}

match work_with_file().unwrap_err() {
    MyError::IoError(_, "working with file") => (),
    _ => panic!("wrong context"),
}

fn do_stuff() -> Result<(), MyError> {
    wrap_in_context_of("doing stuff", || {
        Err(io::Error::new(io::ErrorKind::InvalidInput, "boom!"))?;
        Ok(())
    })?;
    Ok(())
}

match do_stuff().unwrap_err() {
    MyError::IoError(_, "doing stuff") => (),
    _ => panic!("wrong context"),
}

Usage guidelines

  • Use error context to provide information about which good program path was taken that lead to an error, e.g: "while parsing filed x of message type y".
  • Error context should provide detail for the end user who sees the error message and not be used to distinguish between two different errors in code - use Display types like &'static str as context type.
  • Don't add errors or error path information to context - this should be part of the error type, in particular its Display and Error::source implementation.
  • Don't add arguments of function call you are rising error from to the context - this should be responsibility of the caller - otherwise it would be difficult to avoid non-'static references or allocations on error path and avoid showing sensitive data to end user, e.g. SQL query text or passwords.
  • Don't put non-'static references to context or the error value cannot be bubbled up easily or returned as Error::source.

Modules

prelude

Includes WithContext trait, ErrorContext, ErrorNoContext types and related conversion traits and *in_context_of* functions

Structs

ErrorContext

Wrap error value together with context information

ErrorNoContext

Wrap value in ErrorNoContext to add more context using WithContext trait that will convert it to ErrorContext

Traits

MapErrorNoContext

Map error caring type by wrapping it's error value in ErrorNoContext

ResultErrorWhile

Add context to error carried by another type like Result

ResultErrorWhileWrap

Result extension trait to wrap error value in ErrorContext with given context information

ToErrorNoContext

Wrap value with ErrorNoContext

WithContext

Add context to object

WrapContext

Wrap value in type with context information

Functions

in_context_of

Executes closure adding context to returned error value with .with_context(context)

in_context_of_with

Executes closure adding context to returned error value with .with_context(context) obtaining context by calling given function on error path

wrap_in_context_of

Executes closure adding context to returned error value by wrapping it in ErrorContext with .wrap_context(context)

wrap_in_context_of_with

Executes closure adding context to returned error value by wrapping it in ErrorContext with .wrap_context(context) obtaining context by calling given function on error path