diff --git a/src/error.rs b/src/error.rs index 8834059f..21b5526f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -40,6 +40,30 @@ impl fmt::Display for Error { } } +impl Error { + /// Return true if the underlying error has the same type as T. + pub fn is(&self) -> bool { + self.get_ref().is::() + } + + /// Return a reference to the lower level, inner error. + pub fn get_ref(&self) -> &(error::Error + 'static) { + use self::ErrorKind::*; + + match self.inner { + StatusCode(ref e) => e, + Method(ref e) => e, + Uri(ref e) => e, + UriShared(ref e) => e, + UriParts(ref e) => e, + HeaderName(ref e) => e, + HeaderNameShared(ref e) => e, + HeaderValue(ref e) => e, + HeaderValueShared(ref e) => e, + } + } +} + impl error::Error for Error { fn description(&self) -> &str { use self::ErrorKind::*; @@ -56,6 +80,13 @@ impl error::Error for Error { HeaderValueShared(ref e) => e.description(), } } + + // Return any available cause from the inner error. Note the inner error is + // not itself the cause. + #[allow(deprecated)] + fn cause(&self) -> Option<&error::Error> { + self.get_ref().cause() + } } impl From for Error { @@ -142,3 +173,23 @@ impl error::Error for Never { } } +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn inner_error_is_invalid_status_code() { + if let Err(e) = status::StatusCode::from_u16(6666) { + let err: Error = e.into(); + let ie = err.get_ref(); + assert!(!ie.is::()); + assert!( ie.is::()); + ie.downcast_ref::().unwrap(); + + assert!(!err.is::()); + assert!( err.is::()); + } else { + panic!("Bad status allowed!"); + } + } +}