use std::error; use std::fmt; use std::fmt::Write; #[derive(Debug, Clone)] /// Unexpected is a String which implements the Error trait. It is intended to be used in /// situations where the caller is being given an error they can't really handle, except to pass it /// along or log it. /// /// The error is intended to also implement Send + Sync + Clone, such that it is easy to use in /// async situations. pub struct Unexpected(String); impl fmt::Display for Unexpected { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Unexpected error occurred: {}", self.0) } } impl error::Error for Unexpected {} impl From<&str> for Unexpected { fn from(s: &str) -> Self { Unexpected(s.to_string()) } } pub trait ToUnexpected { fn to_unexpected(&self) -> Unexpected; } impl ToUnexpected for E { fn to_unexpected(&self) -> Unexpected { let mut w = String::new(); write!(w, "{}", self.to_string()).expect("underlying error formatted correctly"); if let Some(src) = self.source() { write!(w, " [{src}]").expect("underyling source formatted correctly"); } Unexpected(w.to_string()) } } pub trait MapUnexpected { fn map_unexpected(self) -> Result; } impl MapUnexpected for Result { fn map_unexpected(self) -> Result { match self { Ok(t) => Ok(t), Err(err) => Err(err.to_unexpected()), } } }