Crate explicit_error_exit

Source
Expand description

Built on top of explicit-error, it provides idiomatic tools to manage errors that ends a process/program. Based on the explicit-error crate, its chore tenet is to favor explicitness by inlining the error output while remaining concise.

The key features are:

  • Explicitly mark any error wrapped in a Result as a Fault, a backtrace is captured.
  • Inline transformation of any errors wrapped in a Result into an Error.
  • A derive macro ExitError to easily declare how enum or struct errors transform into an Error.
  • Add context to errors to help debug.

§A tour of explicit-error-bin

The cornerstone of the library is the Error type. Use Result<T, explicit_error_http::Error>, or equivalently explicit_error_bin::Result<T>, as the return type of any faillible function returning errors that can end the program.

§Inline

In the body of the function you can explicitly turn errors as exit errors using ExitError or marking them as Fault.

use explicit_error_exit::{prelude::*, ExitError, Result, Fault};
use std::process::ExitCode;
// Import the prelude to enable functions on std::result::Result

fn business_logic() -> Result<()> {
    Err(std::io::Error::new(std::io::ErrorKind::Other, "oh no!"))
        .or_fault()?;
    
    // Same behavior as or_fault() but the error is not captured as a source because it does not implement `[std::error::Error]`
    Err("error message").or_fault_no_source()?;

    if 1 > 2 {
        Err(Fault::new()
            .with_context("Usefull context to help debug."))?;
    }

    Err(42).map_err(|e|
        ExitError::new(
            "Something went wrong because ..",
            ExitCode::from(e)
        )
    )?;

    Ok(())
}

§Enum and struct

Domain errors are often represented as enum or struct as they are raised in different places. To easily enable the conversion to Error use the ExitError derive and implement From<&MyError> for ExitError.

use explicit_error_exit::{prelude::*, ExitError, Result, derive::ExitError};
use std::process::ExitCode;

#[derive(ExitError, Debug)]
enum MyError {
    Foo,
}

impl From<&MyError> for ExitError {
    fn from(value: &MyError) -> Self {
        match value {
            MyError::Foo => ExitError::new(
                    "Something went wrong because ..",
                    ExitCode::from(42)
                ),
        }
    }
}

fn business_logic() -> Result<()> {
    Err(MyError::Foo)?;

    Ok(())
}

Note: The ExitError derive implements the conversion to Error, the impl of Display and std::error::Error.

§Pattern matching

One of the drawbacks of using one and only one return type for different domain functions is that callers loose the ability to pattern match on the returned error. A solution is provided using try_map_on_source on any Result<T, Error>, or equivalently explicit_error_exit::Result<T>.

use explicit_error_exit::{prelude::*, ExitError, Result, derive::ExitError};
use std::process::ExitCode;

#[derive(ExitError, Debug)]
enum MyError {
    Foo,
    Bar
}

fn business_logic() -> Result<()> {
    let err: Result<()> = Err(MyError::Foo)?;

    // Do the map if the source's type of the Error is MyError
    err.try_map_on_source(|e| {
        match e {
            MyError::Foo => ExitError::new(
                "Foo",
                ExitCode::SUCCESS),
            MyError::Bar => ExitError::new(
                "Bar",
                ExitCode::FAILURE),
        }
    })?;

    Ok(())
}

Note: under the hood try_map_on_source perform some downcasting.

Modules§

derive
prelude

Structs§

DomainError
Wrapper for errors that are not a Fault. It is used as the explicit_error::Error::Domain variant generic type.
ExitError
Representation of errors that ends a process/program.
Fault
Re-import from explicit_error crate. Wrapper for errors that should not happen but cannot panic. It is wrapped in the Error::Fault variant.

Traits§

ResultDomainWithContext
To use this trait on Result import the prelude use explicit_error_exit::prelude::*
ToDomainError
Internally used by ExitError derive.

Type Aliases§

Error
Result