1 /*! 2 Iterate over error `.source()` chains. 3 4 NOTE: This module is taken wholesale from <https://crates.io/crates/eyre>. 5 */ 6 use std::error::Error as StdError; 7 use std::vec; 8 9 use ChainState::*; 10 11 /// Iterator of a chain of source errors. 12 /// 13 /// This type is the iterator returned by [`Report::chain`]. 14 /// 15 /// # Example 16 /// 17 /// ``` 18 /// use miette::Report; 19 /// use std::io; 20 /// 21 /// pub fn underlying_io_error_kind(error: &Report) -> Option<io::ErrorKind> { 22 /// for cause in error.chain() { 23 /// if let Some(io_error) = cause.downcast_ref::<io::Error>() { 24 /// return Some(io_error.kind()); 25 /// } 26 /// } 27 /// None 28 /// } 29 /// ``` 30 #[derive(Clone)] 31 #[allow(missing_debug_implementations)] 32 pub struct Chain<'a> { 33 state: crate::chain::ChainState<'a>, 34 } 35 36 #[derive(Clone)] 37 pub(crate) enum ChainState<'a> { 38 Linked { 39 next: Option<&'a (dyn StdError + 'static)>, 40 }, 41 Buffered { 42 rest: vec::IntoIter<&'a (dyn StdError + 'static)>, 43 }, 44 } 45 46 impl<'a> Chain<'a> { new(head: &'a (dyn StdError + 'static)) -> Self47 pub(crate) fn new(head: &'a (dyn StdError + 'static)) -> Self { 48 Chain { 49 state: ChainState::Linked { next: Some(head) }, 50 } 51 } 52 } 53 54 impl<'a> Iterator for Chain<'a> { 55 type Item = &'a (dyn StdError + 'static); 56 next(&mut self) -> Option<Self::Item>57 fn next(&mut self) -> Option<Self::Item> { 58 match &mut self.state { 59 Linked { next } => { 60 let error = (*next)?; 61 *next = error.source(); 62 Some(error) 63 } 64 Buffered { rest } => rest.next(), 65 } 66 } 67 size_hint(&self) -> (usize, Option<usize>)68 fn size_hint(&self) -> (usize, Option<usize>) { 69 let len = self.len(); 70 (len, Some(len)) 71 } 72 } 73 74 impl DoubleEndedIterator for Chain<'_> { next_back(&mut self) -> Option<Self::Item>75 fn next_back(&mut self) -> Option<Self::Item> { 76 match &mut self.state { 77 Linked { mut next } => { 78 let mut rest = Vec::new(); 79 while let Some(cause) = next { 80 next = cause.source(); 81 rest.push(cause); 82 } 83 let mut rest = rest.into_iter(); 84 let last = rest.next_back(); 85 self.state = Buffered { rest }; 86 last 87 } 88 Buffered { rest } => rest.next_back(), 89 } 90 } 91 } 92 93 impl ExactSizeIterator for Chain<'_> { len(&self) -> usize94 fn len(&self) -> usize { 95 match &self.state { 96 Linked { mut next } => { 97 let mut len = 0; 98 while let Some(cause) = next { 99 next = cause.source(); 100 len += 1; 101 } 102 len 103 } 104 Buffered { rest } => rest.len(), 105 } 106 } 107 } 108 109 impl Default for Chain<'_> { default() -> Self110 fn default() -> Self { 111 Chain { 112 state: ChainState::Buffered { 113 rest: Vec::new().into_iter(), 114 }, 115 } 116 } 117 } 118