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