Skip to content

Commit

Permalink
Add http::Error::inner_ref and cause (#303)
Browse files Browse the repository at this point in the history
* add Error::inner_ref() for access to inner error type

Also use `Error::inner_ref` to implement `std::error::Error::cause`
for now. When MSRV is raised to 1.30.0+, this could also be used for
`Error::source` without a breaking change.

* add Error::is helper

* rename Error::inner_ref to get_ref

* make Error::cause be the inner error's cause

None of the inner errors currently have a cause, but this is
considered (see PR discussion) the most correct implementation of
`std::error::Error::cause` and is thus future proofed.
  • Loading branch information
dekellum authored and seanmonstar committed Apr 2, 2019
1 parent ffe719c commit 5073ffd
Showing 1 changed file with 51 additions and 0 deletions.
51 changes: 51 additions & 0 deletions src/error.rs
Expand Up @@ -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<T: error::Error + 'static>(&self) -> bool {
self.get_ref().is::<T>()
}

/// 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::*;
Expand All @@ -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<status::InvalidStatusCode> for Error {
Expand Down Expand Up @@ -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::<header::InvalidHeaderValue>());
assert!( ie.is::<status::InvalidStatusCode>());
ie.downcast_ref::<status::InvalidStatusCode>().unwrap();

assert!(!err.is::<header::InvalidHeaderValue>());
assert!( err.is::<status::InvalidStatusCode>());
} else {
panic!("Bad status allowed!");
}
}
}

0 comments on commit 5073ffd

Please sign in to comment.