1use std::{error, fmt, result};
2
3pub use http::header::InvalidHeaderName;
4pub use http::method::InvalidMethod;
5pub use http::status::InvalidStatusCode;
6pub use http::uri::InvalidUri;
7
8pub use crate::value::{InvalidHeaderValue, ToStrError};
9
10use http::header;
11use http::method;
12use http::status;
13use http::uri;
14
15pub struct Error {
22 inner: ErrorKind,
23}
24
25pub type Result<T> = result::Result<T, Error>;
27
28enum ErrorKind {
29 StatusCode(status::InvalidStatusCode),
30 Method(method::InvalidMethod),
31 Uri(uri::InvalidUri),
32 UriParts(uri::InvalidUriParts),
33 HeaderName(header::InvalidHeaderName),
34 HeaderValue(InvalidHeaderValue),
35 Http(http::Error),
36}
37
38impl fmt::Debug for Error {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.debug_tuple("ntex_http::Error")
41 .field(&self.get_ref())
43 .finish()
44 }
45}
46
47impl fmt::Display for Error {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 fmt::Display::fmt(self.get_ref(), f)
50 }
51}
52
53impl Error {
54 pub fn is<T: error::Error + 'static>(&self) -> bool {
56 self.get_ref().is::<T>()
57 }
58
59 pub fn get_ref(&self) -> &(dyn error::Error + 'static) {
61 use self::ErrorKind::*;
62
63 match self.inner {
64 StatusCode(ref e) => e,
65 Method(ref e) => e,
66 Uri(ref e) => e,
67 UriParts(ref e) => e,
68 HeaderName(ref e) => e,
69 HeaderValue(ref e) => e,
70 Http(ref e) => e,
71 }
72 }
73}
74
75impl error::Error for Error {
76 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
79 self.get_ref().source()
80 }
81}
82
83impl From<status::InvalidStatusCode> for Error {
84 fn from(err: status::InvalidStatusCode) -> Error {
85 Error {
86 inner: ErrorKind::StatusCode(err),
87 }
88 }
89}
90
91impl From<method::InvalidMethod> for Error {
92 fn from(err: method::InvalidMethod) -> Error {
93 Error {
94 inner: ErrorKind::Method(err),
95 }
96 }
97}
98
99impl From<uri::InvalidUri> for Error {
100 fn from(err: uri::InvalidUri) -> Error {
101 Error {
102 inner: ErrorKind::Uri(err),
103 }
104 }
105}
106
107impl From<uri::InvalidUriParts> for Error {
108 fn from(err: uri::InvalidUriParts) -> Error {
109 Error {
110 inner: ErrorKind::UriParts(err),
111 }
112 }
113}
114
115impl From<header::InvalidHeaderName> for Error {
116 fn from(err: header::InvalidHeaderName) -> Error {
117 Error {
118 inner: ErrorKind::HeaderName(err),
119 }
120 }
121}
122
123impl From<InvalidHeaderValue> for Error {
124 fn from(err: InvalidHeaderValue) -> Error {
125 Error {
126 inner: ErrorKind::HeaderValue(err),
127 }
128 }
129}
130
131impl From<http::Error> for Error {
132 fn from(err: http::Error) -> Error {
133 Error {
134 inner: ErrorKind::Http(err),
135 }
136 }
137}
138
139impl From<std::convert::Infallible> for Error {
140 fn from(err: std::convert::Infallible) -> Error {
141 match err {}
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use std::error::Error as StdError;
149
150 #[test]
151 fn inner_http_error() {
152 let e = method::Method::from_bytes(b"").unwrap_err();
153 let err: Error = http::Error::from(e).into();
154 let ie = err.get_ref();
155 assert!(ie.is::<http::Error>());
156 }
157
158 #[test]
159 fn inner_error_is_invalid_status_code() {
160 let e = status::StatusCode::from_u16(6666).unwrap_err();
161 let err: Error = e.into();
162 let ie = err.get_ref();
163 assert!(!ie.is::<header::InvalidHeaderValue>());
164 assert!(ie.is::<status::InvalidStatusCode>());
165 ie.downcast_ref::<status::InvalidStatusCode>().unwrap();
166
167 assert!(err.source().is_none());
168 assert!(!err.is::<InvalidHeaderValue>());
169 assert!(err.is::<status::InvalidStatusCode>());
170
171 let s = format!("{:?}", err);
172 assert!(s.starts_with("ntex_http::Error"));
173 }
174
175 #[test]
176 fn inner_error_is_invalid_method() {
177 let e = method::Method::from_bytes(b"").unwrap_err();
178 let err: Error = e.into();
179 let ie = err.get_ref();
180 assert!(ie.is::<method::InvalidMethod>());
181 ie.downcast_ref::<method::InvalidMethod>().unwrap();
182
183 assert!(err.source().is_none());
184 assert!(err.is::<method::InvalidMethod>());
185
186 let s = format!("{:?}", err);
187 assert!(s.starts_with("ntex_http::Error"));
188 }
189}