Crate fused_error
source · [−]Expand description
A simple library for working with composable errors.
Examples
Basic usage:
use std::{
num::{IntErrorKind, ParseIntError},
iter::Sum,
str::FromStr
};
use fused_error::{Accumulator, FusedResult, IteratorExt};
/// Take an iterator of textual data, adding up all of the parsed numbers.
///
/// Unlike the standard way of returning a `Result<N, N::Err>`, this doesn't
/// short-circuit, it keeps track of the current sum, and reports any
/// further diagnostics past the first failure.
fn calculate_sum<N, E, I>(iter: I) -> FusedResult<N, N::Err>
where
N: FromStr + Sum,
E: AsRef<str>,
I: IntoIterator<Item = E>,
{
// Error accumulators collect errors to defer handling them, providing
// more holistic diagnostics:
let mut acc = Accumulator::new();
let sum = iter
.into_iter()
.map(|item| item.as_ref().parse::<N>())
// `fused_error` adds certain methods to iterators; no more
// disrupting iterator chains and `collect` hells for results!
.accumulate(&mut acc)
.sum();
// fused results let you easily pass around error accumulators and
// are perfect for cases where a yielded "ok" value and an error case
// aren't mutually exclusive.
FusedResult::new(sum, acc)
}
let result: FusedResult<i32, _> = calculate_sum(["1", "2", "3", "4"]);
assert_eq!(result.value(), &10);
assert_eq!(result.errors(), []);
let result: FusedResult<i8, _> = calculate_sum(["", "-129", "foo", "128"]);
assert_eq!(result.value(), &0);
assert_eq!(
result
.errors()
.into_iter()
.map(|err| err.kind().clone())
.collect::<Vec<_>>(),
[
IntErrorKind::Empty,
IntErrorKind::NegOverflow,
IntErrorKind::InvalidDigit,
IntErrorKind::PosOverflow,
],
);
let result: FusedResult<u8, _> = calculate_sum(["-1", "", "0", "1"]);
assert_eq!(result.value(), &1);
assert_eq!(
result
.errors()
.into_iter()
.map(|err| err.kind().clone())
.collect::<Vec<_>>(),
[IntErrorKind::InvalidDigit, IntErrorKind::Empty],
);
Features
So far, there is only one opt-in feature: syn
. Enabling this feature
implements FusedError
on syn::Error
, as that was one of the main
motivations for creating this library.
Motivation
syn
already has great composable errors that you combine with
syn::Error::combine
. Also, darling
has a great system that was the
primary inspiration for error accumulators and their drop mechanic. However,
of course, darling
’s accumulators are only to be used with darling
errors and their accumulator API is far more limited to reflect this.
The original use case for this crate, deferring and collecting multiple errors, is primarily helpful in parsing: the more diagnostics you can provide in one pass limits the need of frequently changing something, building, fixing the one error, and trying again.
Modules
Accumulated<E>
.Accumulator<E>
.IteratorExt
.FusedResult<T, E>
.Structs
FusedError
.Accumulator<E>
with a persistently “ok”
value of T
.Traits
Iterator
with methods for complex error handling:Type Definitions
FusedResult<T, E>
that can short-circuit with an
error, dropping the “ok” value.