1 use self::ChainState::*;
2 use crate::StdError;
3 
4 #[cfg(feature = "std")]
5 use std::vec;
6 
7 #[cfg(feature = "std")]
8 pub(crate) use crate::Chain;
9 
10 #[cfg(not(feature = "std"))]
11 pub(crate) struct Chain<'a> {
12     state: ChainState<'a>,
13 }
14 
15 #[derive(Clone)]
16 pub(crate) enum ChainState<'a> {
17     Linked {
18         next: Option<&'a (dyn StdError + 'static)>,
19     },
20     #[cfg(feature = "std")]
21     Buffered {
22         rest: vec::IntoIter<&'a (dyn StdError + 'static)>,
23     },
24 }
25 
26 impl<'a> Chain<'a> {
27     #[cold]
new(head: &'a (dyn StdError + 'static)) -> Self28     pub fn new(head: &'a (dyn StdError + 'static)) -> Self {
29         Chain {
30             state: ChainState::Linked { next: Some(head) },
31         }
32     }
33 }
34 
35 impl<'a> Iterator for Chain<'a> {
36     type Item = &'a (dyn StdError + 'static);
37 
next(&mut self) -> Option<Self::Item>38     fn next(&mut self) -> Option<Self::Item> {
39         match &mut self.state {
40             Linked { next } => {
41                 let error = (*next)?;
42                 *next = error.source();
43                 Some(error)
44             }
45             #[cfg(feature = "std")]
46             Buffered { rest } => rest.next(),
47         }
48     }
49 
size_hint(&self) -> (usize, Option<usize>)50     fn size_hint(&self) -> (usize, Option<usize>) {
51         let len = self.len();
52         (len, Some(len))
53     }
54 }
55 
56 #[cfg(feature = "std")]
57 impl DoubleEndedIterator for Chain<'_> {
next_back(&mut self) -> Option<Self::Item>58     fn next_back(&mut self) -> Option<Self::Item> {
59         match &mut self.state {
60             Linked { mut next } => {
61                 let mut rest = Vec::new();
62                 while let Some(cause) = next {
63                     next = cause.source();
64                     rest.push(cause);
65                 }
66                 let mut rest = rest.into_iter();
67                 let last = rest.next_back();
68                 self.state = Buffered { rest };
69                 last
70             }
71             Buffered { rest } => rest.next_back(),
72         }
73     }
74 }
75 
76 impl ExactSizeIterator for Chain<'_> {
len(&self) -> usize77     fn len(&self) -> usize {
78         match &self.state {
79             Linked { mut next } => {
80                 let mut len = 0;
81                 while let Some(cause) = next {
82                     next = cause.source();
83                     len += 1;
84                 }
85                 len
86             }
87             #[cfg(feature = "std")]
88             Buffered { rest } => rest.len(),
89         }
90     }
91 }
92 
93 #[cfg(feature = "std")]
94 impl Default for Chain<'_> {
default() -> Self95     fn default() -> Self {
96         Chain {
97             state: ChainState::Buffered {
98                 rest: Vec::new().into_iter(),
99             },
100         }
101     }
102 }
103