1 | use self::ChainState::*; |
2 | use crate::StdError; |
3 | |
4 | #[cfg (feature = "std" )] |
5 | use alloc::vec::{self, 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 ] |
28 | 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 | |
38 | fn next(&mut self) -> Option<Self::Item> { |
39 | match &mut self.state { |
40 | Linked { next: &mut Option<&dyn Error> } => { |
41 | let error: &dyn Error = (*next)?; |
42 | *next = error.source(); |
43 | Some(error) |
44 | } |
45 | #[cfg (feature = "std" )] |
46 | Buffered { rest: &mut IntoIter<&dyn Error> } => rest.next(), |
47 | } |
48 | } |
49 | |
50 | fn size_hint(&self) -> (usize, Option<usize>) { |
51 | let len: usize = self.len(); |
52 | (len, Some(len)) |
53 | } |
54 | } |
55 | |
56 | #[cfg (feature = "std" )] |
57 | impl DoubleEndedIterator for Chain<'_> { |
58 | fn next_back(&mut self) -> Option<Self::Item> { |
59 | match &mut self.state { |
60 | Linked { mut next: Option<&dyn Error> } => { |
61 | let mut rest: Vec<&dyn Error> = Vec::new(); |
62 | while let Some(cause: &dyn Error) = next { |
63 | next = cause.source(); |
64 | rest.push(cause); |
65 | } |
66 | let mut rest: IntoIter<&dyn Error> = rest.into_iter(); |
67 | let last: Option<&dyn Error> = rest.next_back(); |
68 | self.state = Buffered { rest }; |
69 | last |
70 | } |
71 | Buffered { rest: &mut IntoIter<&dyn Error> } => rest.next_back(), |
72 | } |
73 | } |
74 | } |
75 | |
76 | impl ExactSizeIterator for Chain<'_> { |
77 | fn len(&self) -> usize { |
78 | match &self.state { |
79 | Linked { mut next: Option<&dyn Error> } => { |
80 | let mut len: usize = 0; |
81 | while let Some(cause: &dyn Error) = next { |
82 | next = cause.source(); |
83 | len += 1; |
84 | } |
85 | len |
86 | } |
87 | #[cfg (feature = "std" )] |
88 | Buffered { rest: &IntoIter<&dyn Error> } => rest.len(), |
89 | } |
90 | } |
91 | } |
92 | |
93 | #[cfg (feature = "std" )] |
94 | impl Default for Chain<'_> { |
95 | fn default() -> Self { |
96 | Chain { |
97 | state: ChainState::Buffered { |
98 | rest: Vec::new().into_iter(), |
99 | }, |
100 | } |
101 | } |
102 | } |
103 | |