eyre/
chain.rs

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