eyre/chain.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
use self::ChainState::*;
use crate::StdError;
use std::vec;
pub(crate) use crate::Chain;
#[derive(Clone)]
pub(crate) enum ChainState<'a> {
Linked {
next: Option<&'a (dyn StdError + 'static)>,
},
Buffered {
rest: vec::IntoIter<&'a (dyn StdError + 'static)>,
},
}
impl<'a> Chain<'a> {
/// Construct an iterator over a chain of errors via the `source` method
///
/// # Example
///
/// ```rust
/// use std::error::Error;
/// use std::fmt::{self, Write};
/// use eyre::Chain;
/// use indenter::indented;
///
/// fn report(error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let mut errors = Chain::new(error).enumerate();
/// for (i, error) in errors {
/// writeln!(f)?;
/// write!(indented(f).ind(i), "{}", error)?;
/// }
///
/// Ok(())
/// }
/// ```
pub fn new(head: &'a (dyn StdError + 'static)) -> Self {
Chain {
state: ChainState::Linked { next: Some(head) },
}
}
}
impl<'a> Iterator for Chain<'a> {
type Item = &'a (dyn StdError + 'static);
fn next(&mut self) -> Option<Self::Item> {
match &mut self.state {
Linked { next } => {
let error = (*next)?;
*next = error.source();
Some(error)
}
Buffered { rest } => rest.next(),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl DoubleEndedIterator for Chain<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
match &mut self.state {
Linked { mut next } => {
let mut rest = Vec::new();
while let Some(cause) = next {
next = cause.source();
rest.push(cause);
}
let mut rest = rest.into_iter();
let last = rest.next_back();
self.state = Buffered { rest };
last
}
Buffered { rest } => rest.next_back(),
}
}
}
impl ExactSizeIterator for Chain<'_> {
fn len(&self) -> usize {
match &self.state {
Linked { mut next } => {
let mut len = 0;
while let Some(cause) = next {
next = cause.source();
len += 1;
}
len
}
Buffered { rest } => rest.len(),
}
}
}
impl Default for Chain<'_> {
fn default() -> Self {
Chain {
state: ChainState::Buffered {
rest: Vec::new().into_iter(),
},
}
}
}