use std::fmt;
#[derive(Debug)]
pub enum KnafehError {
Transport(String),
Codec(String),
Service {
code: RpcStatusCode,
message: String,
},
Timeout,
InvalidMessage(String),
ConnectionClosed,
Tls(String),
Io(std::io::Error),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
pub enum RpcStatusCode {
Ok = 0,
Cancelled = 1,
Unknown = 2,
InvalidArgument = 3,
DeadlineExceeded = 4,
NotFound = 5,
AlreadyExists = 6,
PermissionDenied = 7,
ResourceExhausted = 8,
FailedPrecondition = 9,
Aborted = 10,
OutOfRange = 11,
Unimplemented = 12,
Internal = 13,
Unavailable = 14,
DataLoss = 15,
Unauthenticated = 16,
}
impl fmt::Display for KnafehError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Transport(msg) => write!(f, "transport error: {msg}"),
Self::Codec(msg) => write!(f, "codec error: {msg}"),
Self::Service { code, message } => {
write!(f, "service error ({code:?}): {message}")
}
Self::Timeout => write!(f, "request timed out"),
Self::InvalidMessage(msg) => write!(f, "invalid message: {msg}"),
Self::ConnectionClosed => write!(f, "connection closed"),
Self::Tls(msg) => write!(f, "TLS error: {msg}"),
Self::Io(err) => write!(f, "I/O error: {err}"),
}
}
}
impl std::error::Error for KnafehError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io(err) => Some(err),
_ => None,
}
}
}
impl From<std::io::Error> for KnafehError {
fn from(err: std::io::Error) -> Self {
Self::Io(err)
}
}
impl From<serde_json::Error> for KnafehError {
fn from(err: serde_json::Error) -> Self {
Self::Codec(err.to_string())
}
}
#[cfg(feature = "python")]
impl From<KnafehError> for pyo3::PyErr {
fn from(err: KnafehError) -> pyo3::PyErr {
use pyo3::exceptions::*;
match &err {
KnafehError::Transport(_) => PyConnectionError::new_err(err.to_string()),
KnafehError::Codec(_) => PyValueError::new_err(err.to_string()),
KnafehError::Service { .. } => PyRuntimeError::new_err(err.to_string()),
KnafehError::Timeout => PyTimeoutError::new_err(err.to_string()),
KnafehError::InvalidMessage(_) => PyValueError::new_err(err.to_string()),
KnafehError::ConnectionClosed => PyConnectionError::new_err(err.to_string()),
KnafehError::Tls(_) => PyRuntimeError::new_err(err.to_string()),
KnafehError::Io(_) => PyOSError::new_err(err.to_string()),
}
}
}
impl RpcStatusCode {
pub fn from_u8(value: u8) -> Self {
match value {
0 => Self::Ok,
1 => Self::Cancelled,
3 => Self::InvalidArgument,
4 => Self::DeadlineExceeded,
5 => Self::NotFound,
6 => Self::AlreadyExists,
7 => Self::PermissionDenied,
8 => Self::ResourceExhausted,
9 => Self::FailedPrecondition,
10 => Self::Aborted,
11 => Self::OutOfRange,
12 => Self::Unimplemented,
13 => Self::Internal,
14 => Self::Unavailable,
15 => Self::DataLoss,
16 => Self::Unauthenticated,
_ => Self::Unknown,
}
}
}