libimagerror: Move from error-chain to failure
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
This commit is contained in:
parent
c160a967ec
commit
c2f674cc29
4 changed files with 53 additions and 102 deletions
|
@ -20,6 +20,7 @@ is-it-maintained-open-issues = { repository = "matthiasbeyer/imag" }
|
|||
maintenance = { status = "actively-developed" }
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
ansi_term = "0.11"
|
||||
error-chain = "0.12"
|
||||
log = "0.4"
|
||||
ansi_term = "0.11"
|
||||
failure = "0.1"
|
||||
failure_derive = "0.1"
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
//
|
||||
|
||||
use error_chain::ChainedError;
|
||||
use failure::Error;
|
||||
|
||||
/// An iterator that unwraps the `Ok` items of `iter`, while passing the `Err` items to its
|
||||
/// closure `f`.
|
||||
|
@ -31,9 +31,10 @@ pub struct UnwrapWith<I, F>{
|
|||
f: F
|
||||
}
|
||||
|
||||
impl<I, F, T, E> Iterator for UnwrapWith<I, F> where
|
||||
I: Iterator<Item = Result<T, E>>,
|
||||
F: FnMut(E)
|
||||
impl<I, F, T> Iterator for UnwrapWith<I, F>
|
||||
where
|
||||
I: Iterator<Item = Result<T, Error>>,
|
||||
F: FnMut(Error)
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
|
@ -41,14 +42,13 @@ impl<I, F, T, E> Iterator for UnwrapWith<I, F> where
|
|||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
match self.iter.next() {
|
||||
Some(Err(e)) => {
|
||||
(self.f)(e);
|
||||
},
|
||||
Some(Err(e)) => { (self.f)(e); },
|
||||
Some(Ok(item)) => return Some(item),
|
||||
None => return None,
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (_, upper) = self.iter.size_hint();
|
||||
|
@ -56,32 +56,14 @@ impl<I, F, T, E> Iterator for UnwrapWith<I, F> where
|
|||
}
|
||||
}
|
||||
|
||||
impl<I, F, T, E> DoubleEndedIterator for UnwrapWith<I, F> where
|
||||
I: DoubleEndedIterator<Item = Result<T, E>>,
|
||||
F: FnMut(E)
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
match self.iter.next_back() {
|
||||
Some(Err(e)) => {
|
||||
(self.f)(e);
|
||||
},
|
||||
Some(Ok(item)) => return Some(item),
|
||||
None => return None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Iterator helper for Unwrap with exiting on error
|
||||
pub struct UnwrapExit<I, T, E>(I, i32)
|
||||
where I: Iterator<Item = Result<T, E>>,
|
||||
E: ChainedError;
|
||||
pub struct UnwrapExit<I, T>(I, i32)
|
||||
where I: Iterator<Item = Result<T, Error>>;
|
||||
|
||||
impl<I, T, E> Iterator for UnwrapExit<I, T, E>
|
||||
where I: Iterator<Item = Result<T, E>>,
|
||||
E: ChainedError
|
||||
impl<I, T> Iterator for UnwrapExit<I, T>
|
||||
where I: Iterator<Item = Result<T, Error>>,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
|
@ -91,9 +73,8 @@ impl<I, T, E> Iterator for UnwrapExit<I, T, E>
|
|||
}
|
||||
}
|
||||
|
||||
impl<I, T, E> DoubleEndedIterator for UnwrapExit<I, T, E>
|
||||
where I: DoubleEndedIterator<Item = Result<T, E>>,
|
||||
E: ChainedError
|
||||
impl<I, T> DoubleEndedIterator for UnwrapExit<I, T>
|
||||
where I: DoubleEndedIterator<Item = Result<T, Error>>,
|
||||
{
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
use trace::MapErrTrace;
|
||||
|
@ -102,18 +83,21 @@ impl<I, T, E> DoubleEndedIterator for UnwrapExit<I, T, E>
|
|||
}
|
||||
|
||||
/// This trait provides methods that make it easier to work with iterators that yield a `Result`.
|
||||
pub trait TraceIterator<T, E> : Iterator<Item = Result<T, E>> + Sized {
|
||||
/// Creates an iterator that yields the item in each `Ok` item, while filtering out the `Err`
|
||||
pub trait TraceIterator<T> : Iterator<Item = Result<T, Error>> + Sized {
|
||||
/// Creates an iterator that yields the item in each `Ok` item, while filtering out the
|
||||
/// `Err`
|
||||
/// items. Each filtered `Err` will be trace-logged with [`::trace::trace_error`].
|
||||
///
|
||||
/// As with all iterators, the processing is lazy. If you do not use the result of this method,
|
||||
/// nothing will be passed to `::trace::trace_error`, no matter how many `Err` items might
|
||||
/// be present.
|
||||
#[inline]
|
||||
fn trace_unwrap<K>(self) -> UnwrapWith<Self, fn(E)> where E: ChainedError<ErrorKind = K> {
|
||||
fn trace_unwrap(self) -> UnwrapWith<Self, fn(Error)> {
|
||||
#[inline]
|
||||
fn trace_error<K, E: ChainedError<ErrorKind = K>>(err: E) {
|
||||
eprintln!("{}", err.display_chain());
|
||||
fn trace_error(err: Error) {
|
||||
err.iter_chain().for_each(|cause| {
|
||||
eprintln!("{}", cause);
|
||||
});
|
||||
}
|
||||
|
||||
self.unwrap_with(trace_error)
|
||||
|
@ -127,12 +111,11 @@ pub trait TraceIterator<T, E> : Iterator<Item = Result<T, E>> + Sized {
|
|||
/// nothing will be passed to `::trace::trace_error_exit`, no matter how many `Err` items might
|
||||
/// be present.
|
||||
#[inline]
|
||||
fn trace_unwrap_exit(self, exitcode: i32) -> UnwrapExit<Self, T, E>
|
||||
where E: ChainedError
|
||||
{
|
||||
fn trace_unwrap_exit(self, exitcode: i32) -> UnwrapExit<Self, T> {
|
||||
UnwrapExit(self, exitcode)
|
||||
}
|
||||
|
||||
|
||||
/// Takes a closure and creates an iterator that will yield the items inside all `Ok` items
|
||||
/// yielded by the original iterator. All `Err` items will be filtered out, and the contents
|
||||
/// of each `Err` will be passed to the closure.
|
||||
|
@ -141,50 +124,13 @@ pub trait TraceIterator<T, E> : Iterator<Item = Result<T, E>> + Sized {
|
|||
/// for the closure to be called.
|
||||
#[inline]
|
||||
fn unwrap_with<F>(self, f: F) -> UnwrapWith<Self, F>
|
||||
where F: FnMut(E)
|
||||
where F: FnMut(Error)
|
||||
{
|
||||
UnwrapWith { iter: self, f }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T, E> TraceIterator<T, E> for I where
|
||||
I: Iterator<Item = Result<T, E>>
|
||||
impl<I, T> TraceIterator<T> for I where
|
||||
I: Iterator<Item = Result<T, Error>>
|
||||
{}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::TraceIterator;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
struct TestError(i32);
|
||||
|
||||
#[test]
|
||||
fn test_unwrap_with() {
|
||||
let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
|
||||
let mut errs = vec![];
|
||||
|
||||
let oks = original
|
||||
.into_iter()
|
||||
.unwrap_with(|e|errs.push(e))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(&oks, &[1, 3]);
|
||||
assert_eq!(&errs, &[TestError(2), TestError(4)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unwrap_with_backward() {
|
||||
let original = vec![Ok(1), Err(TestError(2)), Ok(3), Err(TestError(4))];
|
||||
let mut errs = vec![];
|
||||
|
||||
let oks = original
|
||||
.into_iter()
|
||||
.rev()
|
||||
.unwrap_with(|e|errs.push(e))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(&oks, &[3, 1]);
|
||||
assert_eq!(&errs, &[TestError(4), TestError(2)]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,11 +35,13 @@
|
|||
|
||||
#[macro_use] extern crate log;
|
||||
extern crate ansi_term;
|
||||
extern crate error_chain;
|
||||
extern crate failure;
|
||||
#[macro_use] extern crate failure_derive;
|
||||
|
||||
pub mod io;
|
||||
pub mod errors;
|
||||
pub mod exit;
|
||||
pub mod trace;
|
||||
pub mod io;
|
||||
pub mod iter;
|
||||
pub mod str;
|
||||
pub mod trace;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ use std::process::exit;
|
|||
use std::fmt::Display;
|
||||
use std::fmt::Formatter;
|
||||
use std::fmt::Result as FmtResult;
|
||||
use error_chain::ChainedError;
|
||||
use failure::Error;
|
||||
use ansi_term::Colour::Red;
|
||||
|
||||
struct ImagTrace<'a, T: 'a + ?Sized>(&'a T);
|
||||
|
@ -32,32 +32,34 @@ impl<'a, T: 'a + ?Sized> ImagTrace<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Display for ImagTrace<'a, T>
|
||||
where T: ChainedError
|
||||
impl<'a> Display for ImagTrace<'a, Error>
|
||||
{
|
||||
fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
|
||||
try!(writeln!(fmt, "{}: {}", Red.blink().paint("ERROR[ 0]"), self.0));
|
||||
let _ = writeln!(fmt, "{}: {}", Red.blink().paint("ERROR[ 0]"), self.0)?;
|
||||
|
||||
for (i, e) in self.0.iter().enumerate().skip(1) {
|
||||
try!(writeln!(fmt, "{}: {}", Red.blink().paint(format!("ERROR[{:>4}]", i)), e));
|
||||
{
|
||||
for (i, cause) in self.0.iter_causes().enumerate() {
|
||||
let _ = writeln!(fmt,
|
||||
"{prefix}: {error}",
|
||||
prefix = Red.blink().paint(format!("ERROR[{:>4}]", i)),
|
||||
error = cause)?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(backtrace) = self.0.backtrace() {
|
||||
try!(writeln!(fmt, "{}", Red.paint("--- BACKTRACE ---")));
|
||||
try!(writeln!(fmt, "{:?}", backtrace));
|
||||
}
|
||||
let _ = writeln!(fmt, "{}", Red.paint("--- BACKTRACE ---"))?;
|
||||
let _ = writeln!(fmt, "{:?}", self.0.backtrace())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn trace_error<K, C: ChainedError<ErrorKind = K>>(e: &C) {
|
||||
pub fn trace_error(e: &Error) {
|
||||
eprintln!("{}", ImagTrace::new(e));
|
||||
}
|
||||
|
||||
pub fn trace_error_dbg<K, C: ChainedError<ErrorKind = K>>(e: &C) {
|
||||
debug!("{}", e.display_chain());
|
||||
pub fn trace_error_dbg(e: &Error) {
|
||||
debug!("{}", ImagTrace::new(e));
|
||||
}
|
||||
|
||||
/// Helper functions for `Result<T, E>` types to reduce overhead in the following situations:
|
||||
|
@ -74,7 +76,7 @@ pub trait MapErrTrace {
|
|||
fn map_err_trace_exit_unwrap(self, code: i32) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<U, K, E: ChainedError<ErrorKind = K>> MapErrTrace for Result<U, E> {
|
||||
impl<U> MapErrTrace for Result<U, Error> {
|
||||
type Output = U;
|
||||
|
||||
/// Simply call `trace_error()` on the Err (if there is one) and return the error.
|
||||
|
|
Loading…
Reference in a new issue