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