1use std::fmt;
8
9#[derive(Debug, Clone)]
23pub struct TypeError {
24 message: String,
25}
26
27impl TypeError {
28 pub fn new(message: &str) -> Self {
30 Self {
31 message: message.to_string(),
32 }
33 }
34
35 pub fn message(&self) -> &str {
37 &self.message
38 }
39}
40
41impl fmt::Display for TypeError {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(f, "TypeError: {}", self.message)
44 }
45}
46
47impl std::error::Error for TypeError {}
48
49#[derive(Debug, Clone)]
63pub struct NetworkError {
64 message: String,
65}
66
67impl NetworkError {
68 pub fn new(message: &str) -> Self {
70 Self {
71 message: message.to_string(),
72 }
73 }
74
75 pub fn message(&self) -> &str {
77 &self.message
78 }
79}
80
81impl fmt::Display for NetworkError {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "NetworkError: {}", self.message)
84 }
85}
86
87impl std::error::Error for NetworkError {}
88
89#[derive(Debug, Clone)]
105pub struct AbortError {
106 message: String,
107}
108
109impl AbortError {
110 pub fn new(message: &str) -> Self {
112 Self {
113 message: message.to_string(),
114 }
115 }
116
117 pub fn message(&self) -> &str {
119 &self.message
120 }
121}
122
123impl fmt::Display for AbortError {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 write!(f, "AbortError: {}", self.message)
126 }
127}
128
129impl std::error::Error for AbortError {}
130
131#[derive(Debug)]
169pub enum FetchError {
170 Type(TypeError),
172 Network(NetworkError),
174 Abort(AbortError),
176}
177
178impl fmt::Display for FetchError {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 match self {
181 Self::Type(e) => write!(f, "{}", e),
182 Self::Network(e) => write!(f, "{}", e),
183 Self::Abort(e) => write!(f, "{}", e),
184 }
185 }
186}
187
188impl std::error::Error for FetchError {
189 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
190 match self {
191 Self::Type(e) => Some(e),
192 Self::Network(e) => Some(e),
193 Self::Abort(e) => Some(e),
194 }
195 }
196}
197
198impl From<TypeError> for FetchError {
200 fn from(err: TypeError) -> Self {
201 Self::Type(err)
202 }
203}
204
205impl From<NetworkError> for FetchError {
206 fn from(err: NetworkError) -> Self {
207 Self::Network(err)
208 }
209}
210
211impl From<AbortError> for FetchError {
212 fn from(err: AbortError) -> Self {
213 Self::Abort(err)
214 }
215}
216
217impl From<hyper::Error> for FetchError {
219 fn from(err: hyper::Error) -> Self {
220 Self::Network(NetworkError::new(&err.to_string()))
221 }
222}
223
224impl From<hyper_util::client::legacy::Error> for FetchError {
225 fn from(err: hyper_util::client::legacy::Error) -> Self {
226 Self::Network(NetworkError::new(&err.to_string()))
227 }
228}
229
230impl From<http::Error> for FetchError {
231 fn from(_: http::Error) -> Self {
232 Self::Network(NetworkError::new("HTTP error"))
233 }
234}
235
236impl From<url::ParseError> for FetchError {
237 fn from(_: url::ParseError) -> Self {
238 Self::Type(TypeError::new("Invalid URL"))
239 }
240}
241
242impl From<serde_json::Error> for FetchError {
243 fn from(_: serde_json::Error) -> Self {
244 Self::Type(TypeError::new("JSON parse error"))
245 }
246}
247
248pub type Result<T> = std::result::Result<T, FetchError>;
262
263#[cfg(test)]
264mod tests {
265 use super::*;
266
267 #[test]
268 fn test_error_display() {
269 let type_error = TypeError::new("test message");
270 assert_eq!(format!("{}", type_error), "TypeError: test message");
271
272 let network_error = NetworkError::new("connection failed");
273 assert_eq!(
274 format!("{}", network_error),
275 "NetworkError: connection failed"
276 );
277
278 let abort_error = AbortError::new("aborted");
279 assert_eq!(format!("{}", abort_error), "AbortError: aborted");
280 }
281
282 #[test]
283 fn test_fetch_error_conversions() {
284 let type_error = TypeError::new("test");
285 let fetch_error: FetchError = type_error.into();
286 assert!(matches!(fetch_error, FetchError::Type(_)));
287
288 let network_error = NetworkError::new("test");
289 let fetch_error: FetchError = network_error.into();
290 assert!(matches!(fetch_error, FetchError::Network(_)));
291
292 let abort_error = AbortError::new("test");
293 let fetch_error: FetchError = abort_error.into();
294 assert!(matches!(fetch_error, FetchError::Abort(_)));
295 }
296
297 #[test]
298 fn test_error_messages() {
299 let type_error = TypeError::new("invalid input");
300 assert_eq!(type_error.message(), "invalid input");
301
302 let network_error = NetworkError::new("timeout");
303 assert_eq!(network_error.message(), "timeout");
304
305 let abort_error = AbortError::new("cancelled");
306 assert_eq!(abort_error.message(), "cancelled");
307 }
308}