use std::{error, fmt, io};
use crate::message::Message;
pub type Result<T> = std::result::Result<T, Error>;
pub type SendResult<T> = std::result::Result<T, SendError>;
pub type SendError = (Message, Error);
#[derive(Debug)]
pub struct Error
{
kind: ErrorKind,
}
impl Error
{
pub fn kind(&self) -> ErrorKind
{
self.kind
}
}
impl error::Error for Error {}
impl From<ErrorKind> for Error
{
fn from(kind: ErrorKind) -> Error
{
Error { kind }
}
}
impl From<SendError> for Error
{
fn from((_, e): SendError) -> Error
{
e
}
}
impl From<Error> for io::Error
{
fn from(e: Error) -> io::Error
{
if let ErrorKind::SystemErr(c) = e.kind {
io::Error::from_raw_os_error(c)
} else {
let new_kind = match e.kind {
ErrorKind::Interrupted => io::ErrorKind::Interrupted,
ErrorKind::InvalidInput | ErrorKind::NoArgument => io::ErrorKind::InvalidInput,
ErrorKind::TimedOut => io::ErrorKind::TimedOut,
ErrorKind::TryAgain => io::ErrorKind::WouldBlock,
ErrorKind::ConnectionRefused => io::ErrorKind::ConnectionRefused,
ErrorKind::PermissionDenied => io::ErrorKind::PermissionDenied,
ErrorKind::ConnectionAborted => io::ErrorKind::ConnectionAborted,
ErrorKind::ConnectionReset => io::ErrorKind::ConnectionReset,
ErrorKind::Canceled => io::ErrorKind::Interrupted, ErrorKind::ResourceExists => io::ErrorKind::AlreadyExists,
ErrorKind::BadType => io::ErrorKind::InvalidData,
_ => io::ErrorKind::Other,
};
io::Error::new(new_kind, e)
}
}
}
impl fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
write!(f, "{}", self.kind)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind
{
Interrupted,
OutOfMemory,
InvalidInput,
Busy,
TimedOut,
ConnectionRefused,
Closed,
TryAgain,
NotSupported,
AddressInUse,
IncorrectState,
EntryNotFound,
ProtocolError,
DestUnreachable,
AddressInvalid,
PermissionDenied,
MessageTooLarge,
ConnectionAborted,
ConnectionReset,
Canceled,
OutOfFiles,
OutOfSpace,
ResourceExists,
ReadOnly,
WriteOnly,
Crypto,
PeerAuth,
NoArgument,
Ambiguous,
BadType,
Internal,
SystemErr(i32),
TransportErr(i32),
#[doc(hidden)]
Unknown(i32),
}
impl ErrorKind
{
pub(crate) fn from_code(code: i32) -> ErrorKind
{
match code {
0 => panic!("OK result passed as an error"),
nng_sys::NNG_EINTR => ErrorKind::Interrupted,
nng_sys::NNG_ENOMEM => ErrorKind::OutOfMemory,
nng_sys::NNG_EINVAL => ErrorKind::InvalidInput,
nng_sys::NNG_EBUSY => ErrorKind::Busy,
nng_sys::NNG_ETIMEDOUT => ErrorKind::TimedOut,
nng_sys::NNG_ECONNREFUSED => ErrorKind::ConnectionRefused,
nng_sys::NNG_ECLOSED => ErrorKind::Closed,
nng_sys::NNG_EAGAIN => ErrorKind::TryAgain,
nng_sys::NNG_ENOTSUP => ErrorKind::NotSupported,
nng_sys::NNG_EADDRINUSE => ErrorKind::AddressInUse,
nng_sys::NNG_ESTATE => ErrorKind::IncorrectState,
nng_sys::NNG_ENOENT => ErrorKind::EntryNotFound,
nng_sys::NNG_EPROTO => ErrorKind::ProtocolError,
nng_sys::NNG_EUNREACHABLE => ErrorKind::DestUnreachable,
nng_sys::NNG_EADDRINVAL => ErrorKind::AddressInvalid,
nng_sys::NNG_EPERM => ErrorKind::PermissionDenied,
nng_sys::NNG_EMSGSIZE => ErrorKind::MessageTooLarge,
nng_sys::NNG_ECONNABORTED => ErrorKind::ConnectionAborted,
nng_sys::NNG_ECONNRESET => ErrorKind::ConnectionReset,
nng_sys::NNG_ECANCELED => ErrorKind::Canceled,
nng_sys::NNG_ENOFILES => ErrorKind::OutOfFiles,
nng_sys::NNG_ENOSPC => ErrorKind::OutOfSpace,
nng_sys::NNG_EEXIST => ErrorKind::ResourceExists,
nng_sys::NNG_EREADONLY => ErrorKind::ReadOnly,
nng_sys::NNG_EWRITEONLY => ErrorKind::WriteOnly,
nng_sys::NNG_ECRYPTO => ErrorKind::Crypto,
nng_sys::NNG_EPEERAUTH => ErrorKind::PeerAuth,
nng_sys::NNG_ENOARG => ErrorKind::NoArgument,
nng_sys::NNG_EAMBIGUOUS => ErrorKind::Ambiguous,
nng_sys::NNG_EBADTYPE => ErrorKind::BadType,
nng_sys::NNG_EINTERNAL => ErrorKind::Internal,
c if c & nng_sys::NNG_ESYSERR != 0 => ErrorKind::SystemErr(c & !nng_sys::NNG_ESYSERR),
c if c & nng_sys::NNG_ETRANERR != 0 => ErrorKind::TransportErr(c & !nng_sys::NNG_ETRANERR),
_ => ErrorKind::Unknown(code),
}
}
}
impl fmt::Display for ErrorKind
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
{
match *self {
ErrorKind::Interrupted => write!(f, "Interrupted"),
ErrorKind::OutOfMemory => write!(f, "Out of memory"),
ErrorKind::InvalidInput => write!(f, "Invalid argument"),
ErrorKind::Busy => write!(f, "Resource busy"),
ErrorKind::TimedOut => write!(f, "Timed out"),
ErrorKind::ConnectionRefused => write!(f, "Connection refused"),
ErrorKind::Closed => write!(f, "Object closed"),
ErrorKind::TryAgain => write!(f, "Try again"),
ErrorKind::NotSupported => write!(f, "Not supported"),
ErrorKind::AddressInUse => write!(f, "Address in use"),
ErrorKind::IncorrectState => write!(f, "Incorrect state"),
ErrorKind::EntryNotFound => write!(f, "Entry not found"),
ErrorKind::ProtocolError => write!(f, "Protocol error"),
ErrorKind::DestUnreachable => write!(f, "Destination unreachable"),
ErrorKind::AddressInvalid => write!(f, "Address invalid"),
ErrorKind::PermissionDenied => write!(f, "Permission denied"),
ErrorKind::MessageTooLarge => write!(f, "Message too large"),
ErrorKind::ConnectionReset => write!(f, "Connection reset"),
ErrorKind::ConnectionAborted => write!(f, "Connection aborted"),
ErrorKind::Canceled => write!(f, "Operation canceled"),
ErrorKind::OutOfFiles => write!(f, "Out of files"),
ErrorKind::OutOfSpace => write!(f, "Out of space"),
ErrorKind::ResourceExists => write!(f, "Resource already exists"),
ErrorKind::ReadOnly => write!(f, "Read only resource"),
ErrorKind::WriteOnly => write!(f, "Write only resource"),
ErrorKind::Crypto => write!(f, "Cryptographic error"),
ErrorKind::PeerAuth => write!(f, "Peer could not be authenticated"),
ErrorKind::NoArgument => write!(f, "Option requires argument"),
ErrorKind::Ambiguous => write!(f, "Ambiguous option"),
ErrorKind::BadType => write!(f, "Incorrect type"),
ErrorKind::Internal => write!(f, "Internal error detected"),
ErrorKind::SystemErr(c) => write!(f, "{}", io::Error::from_raw_os_error(c)),
ErrorKind::TransportErr(c) => write!(f, "Transport error #{}", c),
ErrorKind::Unknown(c) => write!(f, "Unknown error code #{}", c),
}
}
}