1 /*! 2 Iterate over error `.diagnostic_source()` chains. 3 */ 4 5 use crate::protocol::Diagnostic; 6 7 /// Iterator of a chain of cause errors. 8 #[derive(Clone, Default)] 9 #[allow(missing_debug_implementations)] 10 pub(crate) struct DiagnosticChain<'a> { 11 state: Option<ErrorKind<'a>>, 12 } 13 14 impl<'a> DiagnosticChain<'a> { from_diagnostic(head: &'a dyn Diagnostic) -> Self15 pub(crate) fn from_diagnostic(head: &'a dyn Diagnostic) -> Self { 16 DiagnosticChain { 17 state: Some(ErrorKind::Diagnostic(head)), 18 } 19 } 20 from_stderror(head: &'a (dyn std::error::Error + 'static)) -> Self21 pub(crate) fn from_stderror(head: &'a (dyn std::error::Error + 'static)) -> Self { 22 DiagnosticChain { 23 state: Some(ErrorKind::StdError(head)), 24 } 25 } 26 } 27 28 impl<'a> Iterator for DiagnosticChain<'a> { 29 type Item = ErrorKind<'a>; 30 next(&mut self) -> Option<Self::Item>31 fn next(&mut self) -> Option<Self::Item> { 32 if let Some(err) = self.state.take() { 33 self.state = err.get_nested(); 34 Some(err) 35 } else { 36 None 37 } 38 } 39 size_hint(&self) -> (usize, Option<usize>)40 fn size_hint(&self) -> (usize, Option<usize>) { 41 let len = self.len(); 42 (len, Some(len)) 43 } 44 } 45 46 impl ExactSizeIterator for DiagnosticChain<'_> { len(&self) -> usize47 fn len(&self) -> usize { 48 fn depth(d: Option<&ErrorKind<'_>>) -> usize { 49 match d { 50 Some(d) => 1 + depth(d.get_nested().as_ref()), 51 None => 0, 52 } 53 } 54 55 depth(self.state.as_ref()) 56 } 57 } 58 59 #[derive(Clone)] 60 pub(crate) enum ErrorKind<'a> { 61 Diagnostic(&'a dyn Diagnostic), 62 StdError(&'a (dyn std::error::Error + 'static)), 63 } 64 65 impl<'a> ErrorKind<'a> { get_nested(&self) -> Option<ErrorKind<'a>>66 fn get_nested(&self) -> Option<ErrorKind<'a>> { 67 match self { 68 ErrorKind::Diagnostic(d) => d 69 .diagnostic_source() 70 .map(ErrorKind::Diagnostic) 71 .or_else(|| d.source().map(ErrorKind::StdError)), 72 ErrorKind::StdError(e) => e.source().map(ErrorKind::StdError), 73 } 74 } 75 } 76 77 impl<'a> std::fmt::Debug for ErrorKind<'a> { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result78 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 79 match self { 80 ErrorKind::Diagnostic(d) => d.fmt(f), 81 ErrorKind::StdError(e) => e.fmt(f), 82 } 83 } 84 } 85 86 impl<'a> std::fmt::Display for ErrorKind<'a> { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 88 match self { 89 ErrorKind::Diagnostic(d) => d.fmt(f), 90 ErrorKind::StdError(e) => e.fmt(f), 91 } 92 } 93 } 94