use std::io; use err_derive::Error; use log::error; #[derive(Debug, Error)] pub enum Error { #[error(display = "IO error: {}", _0)] Io(#[error(source)] io::Error), #[error(display = "Messagepack encode error: {}", _0)] RMPEncode(#[error(source)] rmp_serde::encode::Error), #[error(display = "Messagepack decode error: {}", _0)] RMPDecode(#[error(source)] rmp_serde::decode::Error), #[error(display = "Tokio join error: {}", _0)] TokioJoin(#[error(source)] tokio::task::JoinError), #[error(display = "oneshot receive error: {}", _0)] OneshotRecv(#[error(source)] tokio::sync::oneshot::error::RecvError), #[error(display = "Handshake error: {}", _0)] Handshake(#[error(source)] kuska_handshake::async_std::Error), #[error(display = "UTF8 error: {}", _0)] UTF8(#[error(source)] std::string::FromUtf8Error), #[error(display = "Framing protocol error")] Framing, #[error(display = "{}", _0)] Message(String), #[error(display = "No handler / shutting down")] NoHandler, #[error(display = "Connection closed")] ConnectionClosed, #[error(display = "Version mismatch: {}", _0)] VersionMismatch(String), #[error(display = "Remote error {}: {}", _0, _1)] Remote(u8, String), } impl Error { pub fn code(&self) -> u8 { match self { Self::Io(_) => 100, Self::TokioJoin(_) => 110, Self::OneshotRecv(_) => 111, Self::RMPEncode(_) => 10, Self::RMPDecode(_) => 11, Self::UTF8(_) => 12, Self::Framing => 13, Self::NoHandler => 20, Self::ConnectionClosed => 21, Self::Handshake(_) => 30, Self::VersionMismatch(_) => 31, Self::Remote(c, _) => *c, Self::Message(_) => 99, } } } impl From> for Error { fn from(_e: tokio::sync::watch::error::SendError) -> Error { Error::Message("Watch send error".into()) } } impl From> for Error { fn from(_e: tokio::sync::mpsc::error::SendError) -> Error { Error::Message("MPSC send error".into()) } } /// Ths trait adds a `.log_err()` method on `Result<(), E>` types, /// which dismisses the error by logging it to stderr. pub trait LogError { fn log_err(self, msg: &'static str); } impl LogError for Result<(), E> where E: Into, { fn log_err(self, msg: &'static str) { if let Err(e) = self { error!("Error: {}: {}", msg, Into::::into(e)); }; } } impl LogError for Result where T: LogError, E: Into, { fn log_err(self, msg: &'static str) { match self { Err(e) => error!("Error: {}: {}", msg, Into::::into(e)), Ok(x) => x.log_err(msg), } } }