use std::{
fmt::{self, Display, Formatter},
io, string,
};
use tokio::io::AsyncRead;
use super::{
binary::TAsyncBinaryProtocol, Message, TInputProtocol, TLengthProtocol, TOutputProtocol,
};
#[derive(Debug)]
pub enum Error {
Transport(TransportError),
Protocol(ProtocolError),
}
impl From<TransportError> for Error {
fn from(e: TransportError) -> Self {
Error::Transport(e)
}
}
impl From<ProtocolError> for Error {
fn from(e: ProtocolError) -> Self {
Error::Protocol(e)
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
match err.kind() {
io::ErrorKind::ConnectionReset
| io::ErrorKind::ConnectionRefused
| io::ErrorKind::NotConnected => Error::Transport(TransportError {
kind: TransportErrorKind::NotOpen,
message: err.to_string(),
}),
io::ErrorKind::AlreadyExists => Error::Transport(TransportError {
kind: TransportErrorKind::AlreadyOpen,
message: err.to_string(),
}),
io::ErrorKind::TimedOut => Error::Transport(TransportError {
kind: TransportErrorKind::TimedOut,
message: err.to_string(),
}),
io::ErrorKind::UnexpectedEof => Error::Transport(TransportError {
kind: TransportErrorKind::EndOfFile,
message: err.to_string(),
}),
_ => {
Error::Transport(TransportError {
kind: TransportErrorKind::Unknown,
message: err.to_string(), })
}
}
}
}
impl From<string::FromUtf8Error> for Error {
fn from(err: string::FromUtf8Error) -> Self {
Error::Protocol(ProtocolError {
kind: ProtocolErrorKind::InvalidData,
message: err.to_string(), })
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl std::error::Error for Error {}
#[derive(Debug, Eq, PartialEq)]
pub struct TransportError {
pub kind: TransportErrorKind,
pub message: String,
}
impl TransportError {
pub fn new<S: Into<String>>(kind: TransportErrorKind, message: S) -> TransportError {
TransportError {
kind,
message: message.into(),
}
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub enum TransportErrorKind {
Unknown = 0,
NotOpen = 1,
AlreadyOpen = 2,
TimedOut = 3,
EndOfFile = 4,
NegativeSize = 5,
SizeLimit = 6,
}
impl Display for TransportError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let error_text = match self.kind {
TransportErrorKind::Unknown => "transport error",
TransportErrorKind::NotOpen => "not open",
TransportErrorKind::AlreadyOpen => "already open",
TransportErrorKind::TimedOut => "timed out",
TransportErrorKind::EndOfFile => "end of file",
TransportErrorKind::NegativeSize => "negative size message",
TransportErrorKind::SizeLimit => "message too long",
};
write!(f, "{} because {}", error_text, self.message)
}
}
impl TryFrom<i32> for TransportErrorKind {
type Error = Error;
fn try_from(from: i32) -> Result<Self, Self::Error> {
match from {
0 => Ok(TransportErrorKind::Unknown),
1 => Ok(TransportErrorKind::NotOpen),
2 => Ok(TransportErrorKind::AlreadyOpen),
3 => Ok(TransportErrorKind::TimedOut),
4 => Ok(TransportErrorKind::EndOfFile),
5 => Ok(TransportErrorKind::NegativeSize),
6 => Ok(TransportErrorKind::SizeLimit),
_ => Err(Error::Protocol(ProtocolError {
kind: ProtocolErrorKind::Unknown,
message: format!("cannot convert {} to TransportErrorKind", from),
})),
}
}
}
pub fn new_transport_error<S: Into<String>>(kind: TransportErrorKind, message: S) -> Error {
Error::Transport(TransportError::new(kind, message))
}
#[derive(Debug, Eq, PartialEq)]
pub struct ProtocolError {
pub kind: ProtocolErrorKind,
pub message: String,
}
impl ProtocolError {
pub fn new<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> ProtocolError {
ProtocolError {
kind,
message: message.into(),
}
}
}
impl Display for ProtocolError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let error_text = match self.kind {
ProtocolErrorKind::Unknown => "protocol error",
ProtocolErrorKind::InvalidData => "bad data",
ProtocolErrorKind::NegativeSize => "negative message size",
ProtocolErrorKind::SizeLimit => "message too long",
ProtocolErrorKind::BadVersion => "invalid thrift version",
ProtocolErrorKind::NotImplemented => "not implemented",
ProtocolErrorKind::DepthLimit => "maximum skip depth reached",
};
write!(f, "{}, {}", error_text, self.message)
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub enum ProtocolErrorKind {
Unknown = 0,
InvalidData = 1,
NegativeSize = 2,
SizeLimit = 3,
BadVersion = 4,
NotImplemented = 5,
DepthLimit = 6,
}
impl TryFrom<i32> for ProtocolErrorKind {
type Error = ProtocolError;
fn try_from(from: i32) -> Result<Self, Self::Error> {
match from {
0 => Ok(ProtocolErrorKind::Unknown),
1 => Ok(ProtocolErrorKind::InvalidData),
2 => Ok(ProtocolErrorKind::NegativeSize),
3 => Ok(ProtocolErrorKind::SizeLimit),
4 => Ok(ProtocolErrorKind::BadVersion),
5 => Ok(ProtocolErrorKind::NotImplemented),
6 => Ok(ProtocolErrorKind::DepthLimit),
_ => Err(ProtocolError {
kind: ProtocolErrorKind::Unknown,
message: format!("cannot convert {} to ProtocolErrorKind", from),
}),
}
}
}
pub fn new_protocol_error<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> Error {
Error::Protocol(ProtocolError::new(kind, message))
}
#[derive(Debug, Clone, Copy)]
pub struct DummyError;
#[async_trait::async_trait]
impl Message for DummyError {
fn encode<T: TOutputProtocol>(&self, _protocol: &mut T) -> Result<(), Error> {
panic!()
}
fn decode<T: TInputProtocol>(_protocol: &mut T) -> Result<Self, Error> {
panic!()
}
async fn decode_async<R>(_protocol: &mut TAsyncBinaryProtocol<R>) -> Result<Self, Error>
where
R: AsyncRead + Unpin + Send,
{
panic!()
}
fn size<T: TLengthProtocol>(&self, _protocol: &T) -> usize {
panic!()
}
}