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
- Working with remote error types using
Accumulated<E>
. - accumulator
- Error accumulation via
Accumulator<E>
. - iter
- Extending iterator functionality with
IteratorExt
. - prelude
- A prelude to import the main items exported by this library:
- result
- Assigning error accumulators to working values with
FusedResult<T, E>
.
Structs§
- Accumulated
- A thin wrapper to handle remote error types as if they implemented
FusedError
. - Accumulator
- An error accumulator.
- Fused
Result - A result type that links an
Accumulator<E>
with a persistently “ok” value ofT
.
Traits§
- Fused
Error - Interface for error types that can store multiple error messages within one instance.
- Into
Result Parts - A trait for splitting a result value into its “ok” and “error” parts.
- Iterator
Ext - Extends
Iterator
with methods for complex error handling:
Type Aliases§
- Packed
Result - A
FusedResult<T, E>
that can short-circuit with an error, dropping the “ok” value.