1use crate::protocol::header::EvictionReason;
7use std::error::Error;
8use std::fmt;
9
10pub type Result<T> = std::result::Result<T, ClientError>;
12
13#[derive(Debug)]
15pub enum ClientError {
16 Connection(String),
18 Protocol(ProtocolError),
20 Evicted(EvictionReason),
22 Timeout,
24 NotRegistered,
26 Shutdown,
28 RequestTooLarge {
30 size: u32,
32 limit: u32,
34 },
35 InvalidOperation,
37 Transport(Box<dyn Error + Send + Sync>),
40}
41
42impl fmt::Display for ClientError {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 match self {
45 ClientError::Connection(msg) => write!(f, "connection error: {}", msg),
46 ClientError::Protocol(e) => write!(f, "protocol error: {}", e),
47 ClientError::Evicted(reason) => write!(f, "client evicted: {:?}", reason),
48 ClientError::Timeout => write!(f, "operation timed out"),
49 ClientError::NotRegistered => write!(f, "client not registered"),
50 ClientError::Shutdown => write!(f, "client is shutting down"),
51 ClientError::RequestTooLarge { size, limit } => {
52 write!(f, "request too large: {} bytes exceeds limit of {} bytes", size, limit)
53 }
54 ClientError::InvalidOperation => write!(f, "invalid operation for current state"),
55 ClientError::Transport(e) => write!(f, "transport error: {}", e),
56 }
57 }
58}
59
60impl Error for ClientError {
61 fn source(&self) -> Option<&(dyn Error + 'static)> {
62 match self {
63 ClientError::Transport(e) => Some(e.as_ref()),
64 ClientError::Protocol(e) => Some(e),
65 _ => None,
66 }
67 }
68}
69
70impl From<ProtocolError> for ClientError {
71 fn from(err: ProtocolError) -> Self {
72 ClientError::Protocol(err)
73 }
74}
75
76impl From<std::io::Error> for ClientError {
77 fn from(err: std::io::Error) -> Self {
78 ClientError::Transport(Box::new(err))
79 }
80}
81
82#[derive(Clone, Copy, Debug, Eq, PartialEq)]
84pub enum ProtocolError {
85 InvalidHeaderChecksum,
87 InvalidBodyChecksum,
89 InvalidHeader,
91 InvalidOperation,
93 UnexpectedReply,
95 VersionMismatch,
97 InvalidSize,
99 InvalidCommand,
101}
102
103impl fmt::Display for ProtocolError {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 match self {
106 ProtocolError::InvalidHeaderChecksum => write!(f, "invalid header checksum"),
107 ProtocolError::InvalidBodyChecksum => write!(f, "invalid body checksum"),
108 ProtocolError::InvalidHeader => write!(f, "invalid header structure"),
109 ProtocolError::InvalidOperation => write!(f, "invalid operation"),
110 ProtocolError::UnexpectedReply => write!(f, "unexpected reply"),
111 ProtocolError::VersionMismatch => write!(f, "version mismatch"),
112 ProtocolError::InvalidSize => write!(f, "invalid message size"),
113 ProtocolError::InvalidCommand => write!(f, "invalid command"),
114 }
115 }
116}
117
118impl Error for ProtocolError {}
119
120#[derive(Clone, Copy, Debug, Eq, PartialEq)]
122pub enum PacketStatus {
123 Ok,
125 TooMuchData,
127 ClientEvicted,
129 ClientReleaseTooLow,
131 ClientReleaseTooHigh,
133 ClientShutdown,
135 InvalidOperation,
137 InvalidDataSize,
139}
140
141impl fmt::Display for PacketStatus {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 match self {
144 PacketStatus::Ok => write!(f, "ok"),
145 PacketStatus::TooMuchData => write!(f, "too much data"),
146 PacketStatus::ClientEvicted => write!(f, "client evicted"),
147 PacketStatus::ClientReleaseTooLow => write!(f, "client release too low"),
148 PacketStatus::ClientReleaseTooHigh => write!(f, "client release too high"),
149 PacketStatus::ClientShutdown => write!(f, "client shutdown"),
150 PacketStatus::InvalidOperation => write!(f, "invalid operation"),
151 PacketStatus::InvalidDataSize => write!(f, "invalid data size"),
152 }
153 }
154}
155
156impl Error for PacketStatus {}
157
158#[derive(Clone, Copy, Debug, Eq, PartialEq)]
160pub enum InitStatus {
161 Success,
163 Unexpected,
165 OutOfMemory,
167 AddressInvalid,
169 AddressLimitExceeded,
171 SystemResources,
173 NetworkSubsystem,
175}
176
177impl fmt::Display for InitStatus {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 match self {
180 InitStatus::Success => write!(f, "success"),
181 InitStatus::Unexpected => write!(f, "unexpected error"),
182 InitStatus::OutOfMemory => write!(f, "out of memory"),
183 InitStatus::AddressInvalid => write!(f, "invalid address"),
184 InitStatus::AddressLimitExceeded => write!(f, "address limit exceeded"),
185 InitStatus::SystemResources => write!(f, "system resources error"),
186 InitStatus::NetworkSubsystem => write!(f, "network subsystem error"),
187 }
188 }
189}
190
191impl Error for InitStatus {}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn test_client_error_display() {
199 let err = ClientError::Timeout;
200 assert_eq!(format!("{}", err), "operation timed out");
201 }
202
203 #[test]
204 fn test_protocol_error_display() {
205 let err = ProtocolError::InvalidHeaderChecksum;
206 assert_eq!(format!("{}", err), "invalid header checksum");
207 }
208
209 #[test]
210 fn test_client_error_from_io() {
211 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
212 let client_err: ClientError = io_err.into();
213 assert!(matches!(client_err, ClientError::Transport(_)));
214 }
215
216 #[test]
217 fn test_error_source_chain() {
218 let protocol_err = ProtocolError::InvalidHeaderChecksum;
219 let client_err = ClientError::Protocol(protocol_err);
220
221 let source = client_err.source().unwrap();
223 assert!(source.is::<ProtocolError>());
224 }
225}