Skip to main content

anyerr/
chain.rs

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}