1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
use std::io; #[derive(Clone, PartialEq, Debug)] pub enum ErrorKind { Io(::std::io::ErrorKind), SerdeJsonSer(::serde_json::error::Category), SerdeJsonDe(String), InterfaceNotFound(String), InvalidParameter(String), MethodNotFound(String), MethodNotImplemented(String), VarlinkErrorReply(crate::Reply), CallContinuesMismatch, MethodCalledAlready, ConnectionBusy, IteratorOldReply, Server, Timeout, ConnectionClosed, InvalidAddress, Generic, } impl ::std::fmt::Display for ErrorKind { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match self { ErrorKind::Io(_) => write!(f, "IO error"), ErrorKind::SerdeJsonSer(_) => write!(f, "JSON Serialization Error"), ErrorKind::SerdeJsonDe(v) => write!(f, "JSON Deserialization Error of '{}'", v), ErrorKind::InterfaceNotFound(v) => write!(f, "Interface not found: '{}'", v), ErrorKind::InvalidParameter(v) => write!(f, "Invalid parameter: '{}'", v), ErrorKind::MethodNotFound(v) => write!(f, "Method not found: '{}'", v), ErrorKind::MethodNotImplemented(v) => write!(f, "Method not implemented: '{}'", v), ErrorKind::VarlinkErrorReply(v) => write!(f, "Varlink error reply: '{:#?}'", v), ErrorKind::CallContinuesMismatch => write!( f, "Call::reply() called with continues, but without more in the request" ), ErrorKind::MethodCalledAlready => write!(f, "Varlink: method called already"), ErrorKind::ConnectionBusy => write!(f, "Varlink: connection busy with other method"), ErrorKind::IteratorOldReply => write!(f, "Varlink: Iterator called on old reply"), ErrorKind::Server => write!(f, "Server Error"), ErrorKind::Timeout => write!(f, "Timeout Error"), ErrorKind::ConnectionClosed => write!(f, "Connection Closed"), ErrorKind::InvalidAddress => write!(f, "Invalid varlink address URI"), ErrorKind::Generic => Ok(()), } } } impl From<&std::io::Error> for ErrorKind { fn from(e: &io::Error) -> Self { match e.kind() { io::ErrorKind::BrokenPipe | io::ErrorKind::ConnectionAborted | io::ErrorKind::ConnectionReset => ErrorKind::ConnectionClosed, kind => ErrorKind::Io(kind), } } } impl From<&serde_json::error::Error> for ErrorKind { fn from(e: &serde_json::error::Error) -> Self { ErrorKind::SerdeJsonSer(e.classify()) } } pub struct Error( pub ErrorKind, pub Option<Box<dyn std::error::Error + 'static + Send + Sync>>, pub Option<&'static str>, ); impl Error { pub fn kind(&self) -> &ErrorKind { &self.0 } } impl From<ErrorKind> for Error { fn from(e: ErrorKind) -> Self { Error(e, None, None) } } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { self.1 .as_ref() .map(|e| e.as_ref() as &(dyn std::error::Error + 'static)) } } impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { std::fmt::Display::fmt(&self.0, f) } } impl std::fmt::Debug for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { use std::error::Error as StdError; if let Some(ref o) = self.2 { std::fmt::Display::fmt(o, f)?; } std::fmt::Debug::fmt(&self.0, f)?; if let Some(e) = self.source() { std::fmt::Display::fmt("\nCaused by:\n", f)?; std::fmt::Debug::fmt(&e, f)?; } Ok(()) } } #[macro_export] macro_rules! map_context { () => { |e| $crate::context!(e, $crate::ErrorKind::from(&e)) }; } #[macro_export] macro_rules! context { ( $k:expr ) => {{ $crate::error::Error($k, None, Some(concat!(file!(), ":", line!(), ": "))) }}; ( None, $k:expr ) => {{ $crate::error::Error($k, None, Some(concat!(file!(), ":", line!(), ": "))) }}; ( $e:path, $k:expr ) => {{ $crate::error::Error( $k, Some(Box::from($e)), Some(concat!(file!(), ":", line!(), ": ")), ) }}; } pub type Result<T> = std::result::Result<T, Error>; #[cfg(test)] mod tests { use static_assertions::assert_impl_all; #[test] fn error_is_sync_send() { assert_impl_all!(crate::error::Error: Send, Sync); } }