use failure::Error;
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct UnwrapWith<I, F>{
iter: I,
f: F
}
impl<I, F, T> Iterator for UnwrapWith<I, F>
where
I: Iterator<Item = Result<T, Error>>,
F: FnMut(Error)
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.iter.next() {
Some(Err(e)) => { (self.f)(e); },
Some(Ok(item)) => return Some(item),
None => return None,
}
}
}
}
pub struct UnwrapExit<I, T>(I)
where I: Iterator<Item = Result<T, Error>>;
impl<I, T> Iterator for UnwrapExit<I, T>
where I: Iterator<Item = Result<T, Error>>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
use crate::trace::MapErrTrace;
self.0.next().map(|e| e.map_err_trace_exit_unwrap())
}
}
impl<I, T> DoubleEndedIterator for UnwrapExit<I, T>
where I: DoubleEndedIterator<Item = Result<T, Error>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
use crate::trace::MapErrTrace;
self.0.next_back().map(|e| e.map_err_trace_exit_unwrap())
}
}
pub trait TraceIterator<T> : Iterator<Item = Result<T, Error>> + Sized {
#[inline]
fn trace_unwrap(self) -> UnwrapWith<Self, fn(Error)> {
#[inline]
fn trace_error(err: Error) {
err.iter_chain().for_each(|cause| {
eprintln!("{}", cause);
});
}
self.unwrap_with(trace_error)
}
#[inline]
fn trace_unwrap_exit(self) -> UnwrapExit<Self, T> {
UnwrapExit(self)
}
#[inline]
fn unwrap_with<F>(self, f: F) -> UnwrapWith<Self, F>
where F: FnMut(Error)
{
UnwrapWith { iter: self, f }
}
}
impl<I, T> TraceIterator<T> for I where
I: Iterator<Item = Result<T, Error>>
{}