eyre_impl/
chain.rs

1use self::ChainState::*;
2
3use std::vec;
4
5/// An iterator over an `Error` and its sources.
6pub 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}