use std::io; use log::error; use thiserror::Error; #[derive(Debug, Error)] pub enum Error { #[error("IO error: {0}")] Io(#[from] io::Error), #[error("Messagepack encode error: {0}")] RMPEncode(#[from] rmp_serde::encode::Error), #[error("Messagepack decode error: {0}")] RMPDecode(#[from] rmp_serde::decode::Error), #[error("Tokio join error: {0}")] TokioJoin(#[from] tokio::task::JoinError), #[error("oneshot receive error: {0}")] OneshotRecv(#[from] tokio::sync::oneshot::error::RecvError), #[error("Handshake error: {0}")] Handshake(#[from] kuska_handshake::async_std::Error), #[error("UTF8 error: {0}")] UTF8(#[from] std::string::FromUtf8Error), #[error("Framing protocol error")] Framing, #[error("Remote error ({0:?}): {1}")] Remote(io::ErrorKind, String), #[error("Request ID collision")] IdCollision, #[error("{0}")] Message(String), #[error("No handler / shutting down")] NoHandler, #[error("Connection closed")] ConnectionClosed, #[error("Version mismatch: {0}")] VersionMismatch(String), } 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()) } } /// The 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), } } } // ---- Helpers for serializing I/O Errors pub(crate) fn u8_to_io_errorkind(v: u8) -> std::io::ErrorKind { use std::io::ErrorKind; match v { 101 => ErrorKind::ConnectionAborted, 102 => ErrorKind::BrokenPipe, 103 => ErrorKind::WouldBlock, 104 => ErrorKind::InvalidInput, 105 => ErrorKind::InvalidData, 106 => ErrorKind::TimedOut, 107 => ErrorKind::Interrupted, 108 => ErrorKind::UnexpectedEof, 109 => ErrorKind::OutOfMemory, 110 => ErrorKind::ConnectionReset, _ => ErrorKind::Other, } } pub(crate) fn io_errorkind_to_u8(kind: std::io::ErrorKind) -> u8 { use std::io::ErrorKind; match kind { ErrorKind::ConnectionAborted => 101, ErrorKind::BrokenPipe => 102, ErrorKind::WouldBlock => 103, ErrorKind::InvalidInput => 104, ErrorKind::InvalidData => 105, ErrorKind::TimedOut => 106, ErrorKind::Interrupted => 107, ErrorKind::UnexpectedEof => 108, ErrorKind::OutOfMemory => 109, ErrorKind::ConnectionReset => 110, _ => 100, } }