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