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 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}