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