1use std::error::Error;
6use std::fmt::{Display, Debug, Formatter};
7use std::io::{ErrorKind, Error as IoError};
8
9pub enum TcpError {
20 Cancelled,
23 TimedOut,
26 Incomplete,
29 TooBig,
32 Failed(IoError)
35}
36
37impl Error for TcpError { }
38
39impl Debug for TcpError {
40 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
41 match self {
42 Self::Cancelled => write!(f, "TcpError::Cancelled"),
43 Self::TimedOut => write!(f, "TcpError::TimedOut"),
44 Self::Incomplete => write!(f, "TcpError::Incomplete"),
45 Self::TooBig => write!(f, "TcpError::TooBig"),
46 Self::Failed(error) => write!(f, "TcpError::Failed({error})"),
47 }
48 }
49}
50
51impl Display for TcpError {
52 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53 match self {
54 Self::Cancelled => write!(f, "The TCP socket operation was cancelled!"),
55 Self::TimedOut => write!(f, "The TCP socket operation timed out!"),
56 Self::Incomplete => write!(f, "The TCP socket operation is incomplete!"),
57 Self::TooBig => write!(f, "The TCP socket operation aborted, data is too big!"),
58 Self::Failed(error) => write!(f, "{error}"),
59 }
60 }
61}
62
63impl From<TcpError> for IoError {
64 fn from(value: TcpError) -> Self {
65 match value {
66 TcpError::Failed(error) => error,
67 other => IoError::new(ErrorKind::Other, other),
68 }
69 }
70}
71
72impl From<IoError> for TcpError {
73 fn from(value: IoError) -> Self {
74 match try_downcast::<TcpError>(value) {
75 Ok(error) => error,
76 Err(other) => TcpError::Failed(other),
77 }
78 }
79}
80
81fn try_downcast<T: Error + 'static>(error: IoError) -> Result<T, IoError> {
82 match error.get_ref().map(|inner| inner.is::<T>()) {
83 Some(true) => Ok(*error.into_inner().unwrap().downcast::<T>().unwrap()),
84 _ => Err(error),
85 }
86}