[−][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 fromVec<woe::Result<T, L, F>
intowoe::Result<Vec<T>, L, F>
via thecollect
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 Name | Channels | Depends On | What It Does |
---|---|---|---|
default | Stable, Beta, Nightly | either_methods | Enables default features (currently just either_methods ). |
nightly | Nightly | try_trait , trusted_len , never_type , termination_trait , product_trait , sum_trait , from_iterator_trait | Enables all nightly-only features. This feature is permanently unstable, and changes to the APIs enabled by this feature are never considered breaking changes. |
no_std | Stable, Beta, Nightly | None | Makes 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_methods | Stable, Beta, Nightly | None | Adds the either crate as a dependency and provides convenience methods for operating on Either<LocalErr, FatalErr> . |
try_trait | Nightly | None | Enables the Try trait, so woe::Result can be used with the question mark operator. |
trusted_len | Nightly | None | Enables woe::Result::{IntoIter, Iter, IterMut} to implement the TrustedLen trait. |
never_type | Nightly | None | Enables the into_ok method if both the LocalErr and FatalErr variant types are ! (the never type). |
termination_trait | Nightly | never_type | Enables woe::Result to be used as the return type for the main function. |
product_trait | Nightly | try_trait | Enables the std::iter::Product trait. |
sum_trait | Nightly | try_trait | Enables the std::iter::Sum trait. |
from_iterator_trait | Nightly | try_trait | Enables the FromIterator trait, which also enables convenient collect ing 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'
)
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 |
Iter | An iterator over a reference to the |
IterMut | An iterator over a mutable reference to the |
Enums
Either | The enum |
Result | A type representing success ( |