fused_error
A simple library for working with composable errors.

Documentation
Module documentation with examples.
Usage
Add this to your Cargo.toml:
[dependencies]
fused_error = "0.1"
Here's a simple example to demonstrate the power of composable errors:
use std::{
num::{IntErrorKind, ParseIntError},
iter::Sum,
str::FromStr
};
use fused_error::{Accumulator, FusedResult, IteratorExt};
fn calculate_sum<N, E, I>(iter: I) -> FusedResult<N, N::Err>
where
N: FromStr + Sum,
E: AsRef<str>,
I: IntoIterator<Item = E>,
{
let mut acc = Accumulator::new();
let sum = iter
.into_iter()
.map(|item| item.as_ref().parse::<N>())
.accumulate(&mut acc)
.sum();
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],
);
Or, when using the syn feature for increased interoperability, here's an
example of fused_error assisting in procedural macros:
use fused_error::{Accumulator, FusedError};
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use syn::{AttributeArgs, DeriveInput, ItemFn};
#[proc_macro_attribute]
pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
fn inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStream2> {
let mut acc = Accumulator::<syn::Error>::new();
let args = acc.handle(parse_args(args));
let item = acc.handle(syn::parse::<ItemFn>(input));
acc = acc.checkpoint()?;
let mut args = unsafe { args.unwrap_unchecked() };
let mut item = unsafe { item.unwrap_unchecked() };
acc.handle(validate_args(&args));
acc.handle(validate_item(&item));
acc = acc.checkpoint()?;
let tokens = acc.handle_in(|| {
prepare(&mut args, &mut item)?;
expand(args, item)
});
acc.err_or_else(|| unsafe { tokens.unwrap_unchecked() })
}
inner(args, input)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
License
Licensed under either of
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.