1 use std::error;
2 use std::fmt;
3 use std::result;
4 
5 use header;
6 use method;
7 use status;
8 use uri;
9 
10 /// A generic "error" for HTTP connections
11 ///
12 /// This error type is less specific than the error returned from other
13 /// functions in this crate, but all other errors can be converted to this
14 /// error. Consumers of this crate can typically consume and work with this form
15 /// of error for conversions with the `?` operator.
16 #[derive(Debug)]
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 #[derive(Debug)]
25 enum ErrorKind {
26     StatusCode(status::InvalidStatusCode),
27     Method(method::InvalidMethod),
28     Uri(uri::InvalidUri),
29     UriShared(uri::InvalidUriBytes),
30     UriParts(uri::InvalidUriParts),
31     HeaderName(header::InvalidHeaderName),
32     HeaderNameShared(header::InvalidHeaderNameBytes),
33     HeaderValue(header::InvalidHeaderValue),
34     HeaderValueShared(header::InvalidHeaderValueBytes),
35 }
36 
37 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result38     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39         error::Error::description(self).fmt(f)
40     }
41 }
42 
43 impl Error {
44     /// Return true if the underlying error has the same type as T.
is<T: error::Error + 'static>(&self) -> bool45     pub fn is<T: error::Error + 'static>(&self) -> bool {
46         self.get_ref().is::<T>()
47     }
48 
49     /// Return a reference to the lower level, inner error.
get_ref(&self) -> &(error::Error + 'static)50     pub fn get_ref(&self) -> &(error::Error + 'static) {
51         use self::ErrorKind::*;
52 
53         match self.inner {
54             StatusCode(ref e) => e,
55             Method(ref e) => e,
56             Uri(ref e) => e,
57             UriShared(ref e) => e,
58             UriParts(ref e) => e,
59             HeaderName(ref e) => e,
60             HeaderNameShared(ref e) => e,
61             HeaderValue(ref e) => e,
62             HeaderValueShared(ref e) => e,
63         }
64     }
65 }
66 
67 impl error::Error for Error {
description(&self) -> &str68     fn description(&self) -> &str {
69         use self::ErrorKind::*;
70 
71         match self.inner {
72             StatusCode(ref e) => e.description(),
73             Method(ref e) => e.description(),
74             Uri(ref e) => e.description(),
75             UriShared(ref e) => e.description(),
76             UriParts(ref e) => e.description(),
77             HeaderName(ref e) => e.description(),
78             HeaderNameShared(ref e) => e.description(),
79             HeaderValue(ref e) => e.description(),
80             HeaderValueShared(ref e) => e.description(),
81         }
82     }
83 
84     // Return any available cause from the inner error. Note the inner error is
85     // not itself the cause.
86     #[allow(deprecated)]
cause(&self) -> Option<&error::Error>87     fn cause(&self) -> Option<&error::Error> {
88         self.get_ref().cause()
89     }
90 }
91 
92 impl From<status::InvalidStatusCode> for Error {
from(err: status::InvalidStatusCode) -> Error93     fn from(err: status::InvalidStatusCode) -> Error {
94         Error { inner: ErrorKind::StatusCode(err) }
95     }
96 }
97 
98 impl From<method::InvalidMethod> for Error {
from(err: method::InvalidMethod) -> Error99     fn from(err: method::InvalidMethod) -> Error {
100         Error { inner: ErrorKind::Method(err) }
101     }
102 }
103 
104 impl From<uri::InvalidUri> for Error {
from(err: uri::InvalidUri) -> Error105     fn from(err: uri::InvalidUri) -> Error {
106         Error { inner: ErrorKind::Uri(err) }
107     }
108 }
109 
110 impl From<uri::InvalidUriBytes> for Error {
from(err: uri::InvalidUriBytes) -> Error111     fn from(err: uri::InvalidUriBytes) -> Error {
112         Error { inner: ErrorKind::UriShared(err) }
113     }
114 }
115 
116 impl From<uri::InvalidUriParts> for Error {
from(err: uri::InvalidUriParts) -> Error117     fn from(err: uri::InvalidUriParts) -> Error {
118         Error { inner: ErrorKind::UriParts(err) }
119     }
120 }
121 
122 impl From<header::InvalidHeaderName> for Error {
from(err: header::InvalidHeaderName) -> Error123     fn from(err: header::InvalidHeaderName) -> Error {
124         Error { inner: ErrorKind::HeaderName(err) }
125     }
126 }
127 
128 impl From<header::InvalidHeaderNameBytes> for Error {
from(err: header::InvalidHeaderNameBytes) -> Error129     fn from(err: header::InvalidHeaderNameBytes) -> Error {
130         Error { inner: ErrorKind::HeaderNameShared(err) }
131     }
132 }
133 
134 impl From<header::InvalidHeaderValue> for Error {
from(err: header::InvalidHeaderValue) -> Error135     fn from(err: header::InvalidHeaderValue) -> Error {
136         Error { inner: ErrorKind::HeaderValue(err) }
137     }
138 }
139 
140 impl From<header::InvalidHeaderValueBytes> for Error {
from(err: header::InvalidHeaderValueBytes) -> Error141     fn from(err: header::InvalidHeaderValueBytes) -> Error {
142         Error { inner: ErrorKind::HeaderValueShared(err) }
143     }
144 }
145 
146 // A crate-private type until we can use !.
147 //
148 // Being crate-private, we should be able to swap the type out in a
149 // backwards compatible way.
150 pub enum Never {}
151 
152 impl From<Never> for Error {
from(never: Never) -> Error153     fn from(never: Never) -> Error {
154         match never {}
155     }
156 }
157 
158 impl fmt::Debug for Never {
fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result159     fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
160         match *self {}
161     }
162 }
163 
164 impl fmt::Display for Never {
fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result165     fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
166         match *self {}
167     }
168 }
169 
170 impl error::Error for Never {
description(&self) -> &str171     fn description(&self) -> &str {
172         match *self {}
173     }
174 }
175 
176 #[cfg(test)]
177 mod tests {
178     use super::*;
179 
180     #[test]
inner_error_is_invalid_status_code()181     fn inner_error_is_invalid_status_code() {
182         if let Err(e) = status::StatusCode::from_u16(6666) {
183             let err: Error = e.into();
184             let ie = err.get_ref();
185             assert!(!ie.is::<header::InvalidHeaderValue>());
186             assert!( ie.is::<status::InvalidStatusCode>());
187             ie.downcast_ref::<status::InvalidStatusCode>().unwrap();
188 
189             assert!(!err.is::<header::InvalidHeaderValue>());
190             assert!( err.is::<status::InvalidStatusCode>());
191         } else {
192             panic!("Bad status allowed!");
193         }
194     }
195 }
196