Line | Count | Source (jump to first uncovered line) |
1 | | use std::error; |
2 | | use std::fmt; |
3 | | use std::result; |
4 | | |
5 | | use crate::header; |
6 | | use crate::header::MaxSizeReached; |
7 | | use crate::method; |
8 | | use crate::status; |
9 | | use crate::uri; |
10 | | |
11 | | /// A generic "error" for HTTP connections |
12 | | /// |
13 | | /// This error type is less specific than the error returned from other |
14 | | /// functions in this crate, but all other errors can be converted to this |
15 | | /// error. Consumers of this crate can typically consume and work with this form |
16 | | /// of error for conversions with the `?` operator. |
17 | | pub struct Error { |
18 | | inner: ErrorKind, |
19 | | } |
20 | | |
21 | | /// A `Result` typedef to use with the `http::Error` type |
22 | | pub type Result<T> = result::Result<T, Error>; |
23 | | |
24 | | enum ErrorKind { |
25 | | StatusCode(status::InvalidStatusCode), |
26 | | Method(method::InvalidMethod), |
27 | | Uri(uri::InvalidUri), |
28 | | UriParts(uri::InvalidUriParts), |
29 | | HeaderName(header::InvalidHeaderName), |
30 | | HeaderValue(header::InvalidHeaderValue), |
31 | | MaxSizeReached(MaxSizeReached), |
32 | | } |
33 | | |
34 | | impl fmt::Debug for Error { |
35 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
36 | 0 | f.debug_tuple("http::Error") |
37 | 0 | // Skip the noise of the ErrorKind enum |
38 | 0 | .field(&self.get_ref()) |
39 | 0 | .finish() |
40 | 0 | } |
41 | | } |
42 | | |
43 | | impl fmt::Display for Error { |
44 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
45 | 0 | fmt::Display::fmt(self.get_ref(), f) |
46 | 0 | } |
47 | | } |
48 | | |
49 | | impl Error { |
50 | | /// Return true if the underlying error has the same type as T. |
51 | 0 | pub fn is<T: error::Error + 'static>(&self) -> bool { |
52 | 0 | self.get_ref().is::<T>() |
53 | 0 | } |
54 | | |
55 | | /// Return a reference to the lower level, inner error. |
56 | 0 | pub fn get_ref(&self) -> &(dyn error::Error + 'static) { |
57 | | use self::ErrorKind::*; |
58 | | |
59 | 0 | match self.inner { |
60 | 0 | StatusCode(ref e) => e, |
61 | 0 | Method(ref e) => e, |
62 | 0 | Uri(ref e) => e, |
63 | 0 | UriParts(ref e) => e, |
64 | 0 | HeaderName(ref e) => e, |
65 | 0 | HeaderValue(ref e) => e, |
66 | 0 | MaxSizeReached(ref e) => e, |
67 | | } |
68 | 0 | } |
69 | | } |
70 | | |
71 | | impl error::Error for Error { |
72 | | // Return any available cause from the inner error. Note the inner error is |
73 | | // not itself the cause. |
74 | 0 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { |
75 | 0 | self.get_ref().source() |
76 | 0 | } |
77 | | } |
78 | | |
79 | | impl From<MaxSizeReached> for Error { |
80 | 0 | fn from(err: MaxSizeReached) -> Error { |
81 | 0 | Error { |
82 | 0 | inner: ErrorKind::MaxSizeReached(err), |
83 | 0 | } |
84 | 0 | } |
85 | | } |
86 | | |
87 | | impl From<status::InvalidStatusCode> for Error { |
88 | 0 | fn from(err: status::InvalidStatusCode) -> Error { |
89 | 0 | Error { |
90 | 0 | inner: ErrorKind::StatusCode(err), |
91 | 0 | } |
92 | 0 | } |
93 | | } |
94 | | |
95 | | impl From<method::InvalidMethod> for Error { |
96 | 0 | fn from(err: method::InvalidMethod) -> Error { |
97 | 0 | Error { |
98 | 0 | inner: ErrorKind::Method(err), |
99 | 0 | } |
100 | 0 | } |
101 | | } |
102 | | |
103 | | impl From<uri::InvalidUri> for Error { |
104 | 3.98k | fn from(err: uri::InvalidUri) -> Error { |
105 | 3.98k | Error { |
106 | 3.98k | inner: ErrorKind::Uri(err), |
107 | 3.98k | } |
108 | 3.98k | } |
109 | | } |
110 | | |
111 | | impl From<uri::InvalidUriParts> for Error { |
112 | 0 | fn from(err: uri::InvalidUriParts) -> Error { |
113 | 0 | Error { |
114 | 0 | inner: ErrorKind::UriParts(err), |
115 | 0 | } |
116 | 0 | } |
117 | | } |
118 | | |
119 | | impl From<header::InvalidHeaderName> for Error { |
120 | 6.32k | fn from(err: header::InvalidHeaderName) -> Error { |
121 | 6.32k | Error { |
122 | 6.32k | inner: ErrorKind::HeaderName(err), |
123 | 6.32k | } |
124 | 6.32k | } |
125 | | } |
126 | | |
127 | | impl From<header::InvalidHeaderValue> for Error { |
128 | 95 | fn from(err: header::InvalidHeaderValue) -> Error { |
129 | 95 | Error { |
130 | 95 | inner: ErrorKind::HeaderValue(err), |
131 | 95 | } |
132 | 95 | } |
133 | | } |
134 | | |
135 | | impl From<std::convert::Infallible> for Error { |
136 | | fn from(err: std::convert::Infallible) -> Error { |
137 | | match err {} |
138 | | } |
139 | | } |
140 | | |
141 | | #[cfg(test)] |
142 | | mod tests { |
143 | | use super::*; |
144 | | |
145 | | #[test] |
146 | | fn inner_error_is_invalid_status_code() { |
147 | | if let Err(e) = status::StatusCode::from_u16(6666) { |
148 | | let err: Error = e.into(); |
149 | | let ie = err.get_ref(); |
150 | | assert!(!ie.is::<header::InvalidHeaderValue>()); |
151 | | assert!(ie.is::<status::InvalidStatusCode>()); |
152 | | ie.downcast_ref::<status::InvalidStatusCode>().unwrap(); |
153 | | |
154 | | assert!(!err.is::<header::InvalidHeaderValue>()); |
155 | | assert!(err.is::<status::InvalidStatusCode>()); |
156 | | } else { |
157 | | panic!("Bad status allowed!"); |
158 | | } |
159 | | } |
160 | | } |