1use std::error::Error as StdError;
5use std::fmt::Display;
6use std::fmt::Formatter;
7use std::fmt::Result as FmtResult;
8use std::str::from_utf8;
9
10use http::Error as HttpError;
11use http::StatusCode as HttpStatusCode;
12
13
14#[derive(Debug)]
19pub enum Error<B>
20where
21 B: StdError,
22{
23 Http(HttpError),
25 HttpStatus(HttpStatusCode, Vec<u8>),
28 Conversion(B),
30}
31
32impl<B> Display for Error<B>
33where
34 B: StdError,
35{
36 fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
37 match self {
38 Error::Http(err) => write!(fmt, "{}", err),
39 Error::HttpStatus(status, data) => {
40 write!(fmt, "HTTP status: {}: ", status)?;
41 match from_utf8(data) {
42 Ok(s) => fmt.write_str(s)?,
43 Err(b) => write!(fmt, "{:?}", b)?,
44 }
45 Ok(())
46 },
47 Error::Conversion(err) => write!(fmt, "{}", err),
48 }
49 }
50}
51
52impl<B> StdError for Error<B>
53where
54 B: StdError,
55{
56 fn source(&self) -> Option<&(dyn StdError + 'static)> {
57 match self {
58 Error::Http(err) => err.source(),
59 Error::HttpStatus(..) => None,
60 Error::Conversion(err) => err.source(),
61 }
62 }
63}
64
65impl<B> From<HttpError> for Error<B>
66where
67 B: StdError,
68{
69 fn from(e: HttpError) -> Self {
70 Error::Http(e)
71 }
72}
73
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79
80 #[test]
82 fn error() {
83 let invalid_status = HttpStatusCode::from_u16(u16::MAX).unwrap_err();
84 let err = Error::<HttpError>::from(HttpError::from(invalid_status));
85 assert_ne!(err.to_string(), "");
86 let src = err.source();
87 assert!(src.is_none(), "{src:?}");
88
89 let invalid_status = HttpStatusCode::from_u16(u16::MAX).unwrap_err();
90 let err = Error::Conversion(HttpError::from(invalid_status));
91 assert_ne!(err.to_string(), "");
92 let src = err.source();
93 assert!(src.is_none(), "{src:?}");
94
95 let err = Error::<HttpError>::HttpStatus(HttpStatusCode::NOT_FOUND, Vec::new());
96 assert_ne!(err.to_string(), "");
97 let src = err.source();
98 assert!(src.is_none(), "{src:?}");
99
100 let err = Error::<HttpError>::HttpStatus(HttpStatusCode::NOT_FOUND, vec![0, 159, 146, 150]);
101 assert_ne!(err.to_string(), "");
102 }
103}