[][src]Crate woe

woe is a Rust crate which provides the following type:

enum Result<T, L, F> {
    Ok(T),
    LocalErr(L),
    FatalErr(F),
}

This type differentiates between "local errors" which can be handled and "fatal errors" which can't, to enable the error handling pattern described by Tyler Neely (@spacejam) in the blog post "Error Handling in a Correctness-Critical Rust Project". woe::Result is intended to be a more ergonomic alternative to the Result<Result<T, LocalError>, FatalError> type proposed in the post.

The important thing to note is that using the question mark operator on woe::Result causes any FatalError to propagate up, while providing Result<T, LocalError> otherwise, to enable the local code to handle any local errors without propagating them.

Features

woe can be used on stable or nightly. On nightly, enabling the nightly feature is recommended, to get the full power of the woe::Result type, including:

  • Being able to use it with the question mark operator,
  • Being able to make it the return type of fn main,
  • Gaining a number of useful additional methods, including from_iter (which enables easy conversion from Vec<woe::Result<T, L, F> into woe::Result<Vec<T>, L, F> via the collect method).

The following table is the full list of features. If you want to use woe without any dependencies, you can disable the either_methods feature, which otherwise imports the either crate to add additional methods.

Feature NameChannelsDepends OnWhat It Does
defaultStable, Beta, Nightlyeither_methodsEnables default features (currently just either_methods).
nightlyNightlytry_trait, trusted_len, never_type, termination_trait, product_trait, sum_trait, from_iterator_traitEnables all nightly-only features. This feature is permanently unstable, and changes to the APIs enabled by this feature are never considered breaking changes.
no_stdStable, Beta, NightlyNoneMakes the crate no_std compatible. This conflicts with the termination_trait feature, so turning on no_std will automatically disable that feature. Use the flag --features no_std,nightly to get a fully-featured and no-std-compatible API.
either_methodsStable, Beta, NightlyNoneAdds the either crate as a dependency and provides convenience methods for operating on Either<LocalErr, FatalErr>.
try_traitNightlyNoneEnables the Try trait, so woe::Result can be used with the question mark operator.
trusted_lenNightlyNoneEnables woe::Result::{IntoIter, Iter, IterMut} to implement the TrustedLen trait.
never_typeNightlyNoneEnables the into_ok method if both the LocalErr and FatalErr variant types are ! (the never type).
termination_traitNightlynever_typeEnables woe::Result to be used as the return type for the main function.
product_traitNightlytry_traitEnables the std::iter::Product trait.
sum_traitNightlytry_traitEnables the std::iter::Sum trait.
from_iterator_traitNightlytry_traitEnables the FromIterator trait, which also enables convenient collecting of Vec<woe::Result<T, L, F>> into woe::Result<Vec<T>, L, F>

Example on stable

use woe::Result::{self, Ok, LocalErr, FatalErr};
use std::result::{Result as StdResult, Result::Ok as StdOk, Result::Err as StdErr};

fn main() {
    match do_thing() {
        StdOk(num) => println!("Got a number: {}", num),
        StdResult::Err(fatal_err) => eprintln!("Fatal error: {:?}", fatal_err),
    }
}

fn do_thing() -> StdResult<i64, FatalError> {
    let result = do_another_thing(5, 5)?;

    // `result` has type `Result<i64, LocalError>`.
    match result {
        StdResult::Err(local_err) => {
            println!("Local error: {:?}", local_err);
            StdOk(i64::default())
        }
        StdOk(num) => StdOk(num),
    }
}

fn do_another_thing(x: i64, y: i64) -> StdResult<StdResult<i64, LocalError>, FatalError> {
    if x > y {
        Ok(x)
    } else if x == y {
        // Make clear which error is the local error ...
        LocalErr(LocalError::SomeError)
    } else {
        // ... and which is the fatal error
        FatalErr(FatalError::CatastrophicError)
    }.into_result()
}

#[derive(Debug)]
enum LocalError {
    SomeError,
    AnotherError,
}

#[derive(Debug)]
enum FatalError {
    BigBadError,
    CatastrophicError,
}

Example on nightly (and using --features 'nightly')

This example is not tested
use std::ops::Try;
use woe::Result::{self, Ok, LocalErr, FatalErr};
use std::result::{Result as StdResult, Result::Ok as StdOk, Result::Err as StdErr};

fn main() {
    match do_thing() {
        StdOk(num) => println!("Got a number: {}", num),
        StdResult::Err(fatal_err) => eprintln!("Fatal error: {:?}", fatal_err),
    }
}

fn do_thing() -> StdResult<i64, FatalError> {
    // `woe::Result` interoperates with `std::result::Result` without issue.
    let result = do_another_thing(5, 5)?;

    // `result` has type `Result<i64, LocalError>`.
    match result {
        StdResult::Err(local_err) => {
            println!("Local error: {:?}", local_err);
            StdOk(i64::default())
        }
        StdOk(num) => StdOk(num),
    }
}

fn do_another_thing(x: i64, y: i64) -> Result<i64, LocalError, FatalError> {
    // `woe::Result` works as expected using the `?` operator with itself.
    let result = do_third_thing(x, y)?;
    // `woe::Result::from_ok` takes in a `Result<T, L>` and returns a `woe::Result<T, L, F>`.
    Result::from_ok(result)
}

fn do_third_thing(x: i64, y: i64) -> Result<i64, LocalError, FatalError> {
    if x > y {
        Ok(x)
    } else if x == y {
        LocalErr(LocalError::SomeError)
    } else {
        FatalErr(FatalError::CatastrophicError)
    }
}

#[derive(Debug)]
enum LocalError {
    SomeError,
    AnotherError,
}

#[derive(Debug)]
enum FatalError {
    BigBadError,
    CatastrophicError,
}

Structs

IntoIter

An iterator over the value in an Ok variant of a woe::Result.

Iter

An iterator over a reference to the Ok variant of a woe::Result.

IterMut

An iterator over a mutable reference to the Ok variant of a woe::Result.

Enums

Either

The enum Either with variants Left and Right is a general purpose sum type with two cases.

Result

A type representing success (Ok), a local error (LocalErr), or a fatal error (FatalErr).