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: &mut Option<&dyn Error> } => {
52 let error: &dyn Error = (*next)?;
53 *next = error.source();
54 Some(error)
55 }
56 Buffered { rest: &mut IntoIter<&dyn Error> } => rest.next(),
57 }
58 }
59
60 fn size_hint(&self) -> (usize, Option<usize>) {
61 let len: usize = 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: Option<&dyn Error> } => {
70 let mut rest: Vec<&dyn Error> = Vec::new();
71 while let Some(cause: &dyn Error) = next {
72 next = cause.source();
73 rest.push(cause);
74 }
75 let mut rest: IntoIter<&dyn Error> = rest.into_iter();
76 let last: Option<&dyn Error> = rest.next_back();
77 self.state = Buffered { rest };
78 last
79 }
80 Buffered { rest: &mut IntoIter<&dyn Error> } => rest.next_back(),
81 }
82 }
83}
84
85impl ExactSizeIterator for Chain<'_> {
86 fn len(&self) -> usize {
87 match &self.state {
88 Linked { mut next: Option<&dyn Error> } => {
89 let mut len: usize = 0;
90 while let Some(cause: &dyn Error) = next {
91 next = cause.source();
92 len += 1;
93 }
94 len
95 }
96 Buffered { rest: &IntoIter<&dyn Error> } => 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}
110