| /*! | |
| Iterate over error `.diagnostic_source()` chains. | |
| */ | |
| use crate::protocol::Diagnostic; | |
| /// Iterator of a chain of cause errors. | |
| #[derive(Clone, Default)] | |
| #[allow(missing_debug_implementations)] | |
| pub(crate) struct DiagnosticChain<'a> { | |
| state: Option<ErrorKind<'a>>, | |
| } | |
| impl<'a> DiagnosticChain<'a> { | |
| pub(crate) fn from_diagnostic(head: &'a dyn Diagnostic) -> Self { | |
| DiagnosticChain { | |
| state: Some(ErrorKind::Diagnostic(head)), | |
| } | |
| } | |
| pub(crate) fn from_stderror(head: &'a (dyn std::error::Error + 'static)) -> Self { | |
| DiagnosticChain { | |
| state: Some(ErrorKind::StdError(head)), | |
| } | |
| } | |
| } | |
| impl<'a> Iterator for DiagnosticChain<'a> { | |
| type Item = ErrorKind<'a>; | |
| fn next(&mut self) -> Option<Self::Item> { | |
| if let Some(err) = self.state.take() { | |
| self.state = err.get_nested(); | |
| Some(err) | |
| } else { | |
| None | |
| } | |
| } | |
| fn size_hint(&self) -> (usize, Option<usize>) { | |
| let len = self.len(); | |
| (len, Some(len)) | |
| } | |
| } | |
| impl ExactSizeIterator for DiagnosticChain<'_> { | |
| fn len(&self) -> usize { | |
| fn depth(d: Option<&ErrorKind<'_>>) -> usize { | |
| match d { | |
| Some(d) => 1 + depth(d.get_nested().as_ref()), | |
| None => 0, | |
| } | |
| } | |
| depth(self.state.as_ref()) | |
| } | |
| } | |
| #[derive(Clone)] | |
| pub(crate) enum ErrorKind<'a> { | |
| Diagnostic(&'a dyn Diagnostic), | |
| StdError(&'a (dyn std::error::Error + 'static)), | |
| } | |
| impl<'a> ErrorKind<'a> { | |
| fn get_nested(&self) -> Option<ErrorKind<'a>> { | |
| match self { | |
| ErrorKind::Diagnostic(d) => d | |
| .diagnostic_source() | |
| .map(ErrorKind::Diagnostic) | |
| .or_else(|| d.source().map(ErrorKind::StdError)), | |
| ErrorKind::StdError(e) => e.source().map(ErrorKind::StdError), | |
| } | |
| } | |
| } | |
| impl<'a> std::fmt::Debug for ErrorKind<'a> { | |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| match self { | |
| ErrorKind::Diagnostic(d) => d.fmt(f), | |
| ErrorKind::StdError(e) => e.fmt(f), | |
| } | |
| } | |
| } | |
| impl<'a> std::fmt::Display for ErrorKind<'a> { | |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| match self { | |
| ErrorKind::Diagnostic(d) => d.fmt(f), | |
| ErrorKind::StdError(e) => e.fmt(f), | |
| } | |
| } | |
| } |