From 146ae4da18038a5dfcc1a6d09aac356baaf0f29f Mon Sep 17 00:00:00 2001
From: Otavio Salvador <otavio@ossystems.com.br>
Date: Tue, 17 Mar 2020 22:51:06 -0300
Subject: [PATCH] Implement `std::error::Error` for our custom errors

For allowing a more ergonomic use and better integration on the
ecosystem, this adds the `std::error::Error` `impl` for our custom
errors.

We intent to drop this hand made code once `derive_more` finishes the
addition of the Error derive support[1]. Until that is available, we
need to live with that.

1. https://github.com/JelteF/derive_more/issues/92

Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
---
 CHANGES.md                     |  8 ++++++++
 actix-http/CHANGES.md          |  8 ++++++++
 actix-http/src/client/error.rs |  8 ++++++++
 actix-http/src/error.rs        |  4 ++++
 actix-http/src/ws/mod.rs       |  2 ++
 awc/CHANGES.md                 |  8 ++++++++
 awc/src/error.rs               |  4 ++++
 src/error.rs                   | 12 ++++++++++++
 8 files changed, 54 insertions(+)

diff --git a/CHANGES.md b/CHANGES.md
index 460b24f5..34908d96 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,13 @@
 # Changes
 
+## [Unreleased]
+
+### Changed
+
+* Implement `std::error::Error` for our custom errors [#1422]
+
+[#1422]: https://github.com/actix/actix-web/pull/1422
+
 ## [3.0.0-alpha.1] - 2020-03-11
 
 ### Added
diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md
index fb1c3a32..9d75e1a0 100644
--- a/actix-http/CHANGES.md
+++ b/actix-http/CHANGES.md
@@ -1,5 +1,13 @@
 # Changes
 
+## [Unreleased]
+
+### Changed
+
+* Implement `std::error::Error` for our custom errors [#1422]
+
+[#1422]: https://github.com/actix/actix-web/pull/1422
+
 ## [2.0.0-alpha.2] - 2020-03-07
 
 ### Changed
diff --git a/actix-http/src/client/error.rs b/actix-http/src/client/error.rs
index 42ea47ee..0f0a86cd 100644
--- a/actix-http/src/client/error.rs
+++ b/actix-http/src/client/error.rs
@@ -55,6 +55,8 @@ pub enum ConnectError {
     Io(io::Error),
 }
 
+impl std::error::Error for ConnectError {}
+
 impl From<actix_connect::ConnectError> for ConnectError {
     fn from(err: actix_connect::ConnectError) -> ConnectError {
         match err {
@@ -86,6 +88,8 @@ pub enum InvalidUrl {
     HttpError(http::Error),
 }
 
+impl std::error::Error for InvalidUrl {}
+
 /// A set of errors that can occur during request sending and response reading
 #[derive(Debug, Display, From)]
 pub enum SendRequestError {
@@ -115,6 +119,8 @@ pub enum SendRequestError {
     Body(Error),
 }
 
+impl std::error::Error for SendRequestError {}
+
 /// Convert `SendRequestError` to a server `Response`
 impl ResponseError for SendRequestError {
     fn status_code(&self) -> StatusCode {
@@ -139,6 +145,8 @@ pub enum FreezeRequestError {
     Http(HttpError),
 }
 
+impl std::error::Error for FreezeRequestError {}
+
 impl From<FreezeRequestError> for SendRequestError {
     fn from(e: FreezeRequestError) -> Self {
         match e {
diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs
index 0850e18f..7ecdc639 100644
--- a/actix-http/src/error.rs
+++ b/actix-http/src/error.rs
@@ -333,6 +333,8 @@ pub enum PayloadError {
     Io(io::Error),
 }
 
+impl std::error::Error for PayloadError {}
+
 impl From<h2::Error> for PayloadError {
     fn from(err: h2::Error) -> Self {
         PayloadError::Http2Payload(err)
@@ -441,6 +443,8 @@ pub enum ContentTypeError {
     UnknownEncoding,
 }
 
+impl std::error::Error for ContentTypeError {}
+
 /// Return `BadRequest` for `ContentTypeError`
 impl ResponseError for ContentTypeError {
     fn status_code(&self) -> StatusCode {
diff --git a/actix-http/src/ws/mod.rs b/actix-http/src/ws/mod.rs
index ffa39797..3d83943c 100644
--- a/actix-http/src/ws/mod.rs
+++ b/actix-http/src/ws/mod.rs
@@ -58,6 +58,8 @@ pub enum ProtocolError {
     Io(io::Error),
 }
 
+impl std::error::Error for ProtocolError {}
+
 impl ResponseError for ProtocolError {}
 
 /// Websocket handshake errors
diff --git a/awc/CHANGES.md b/awc/CHANGES.md
index e6f73154..d127700a 100644
--- a/awc/CHANGES.md
+++ b/awc/CHANGES.md
@@ -1,5 +1,13 @@
 # Changes
 
+## [Unreleased]
+
+### Changed
+
+* Implement `std::error::Error` for our custom errors [#1422]
+
+[#1422]: https://github.com/actix/actix-web/pull/1422
+
 ## [2.0.0-alpha.1] - 2020-03-11
 
 * Update `actix-http` dependency to 2.0.0-alpha.2
diff --git a/awc/src/error.rs b/awc/src/error.rs
index 7fece74e..d008166d 100644
--- a/awc/src/error.rs
+++ b/awc/src/error.rs
@@ -42,6 +42,8 @@ pub enum WsClientError {
     SendRequest(SendRequestError),
 }
 
+impl std::error::Error for WsClientError {}
+
 impl From<InvalidUrl> for WsClientError {
     fn from(err: InvalidUrl) -> Self {
         WsClientError::SendRequest(err.into())
@@ -68,5 +70,7 @@ pub enum JsonPayloadError {
     Payload(PayloadError),
 }
 
+impl std::error::Error for JsonPayloadError {}
+
 /// Return `InternalServerError` for `JsonPayloadError`
 impl ResponseError for JsonPayloadError {}
diff --git a/src/error.rs b/src/error.rs
index 31f6b9c5..659ba05f 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -21,6 +21,8 @@ pub enum UrlGenerationError {
     ParseError(UrlParseError),
 }
 
+impl std::error::Error for UrlGenerationError {}
+
 /// `InternalServerError` for `UrlGeneratorError`
 impl ResponseError for UrlGenerationError {}
 
@@ -51,6 +53,8 @@ pub enum UrlencodedError {
     Payload(PayloadError),
 }
 
+impl std::error::Error for UrlencodedError {}
+
 /// Return `BadRequest` for `UrlencodedError`
 impl ResponseError for UrlencodedError {
     fn status_code(&self) -> StatusCode {
@@ -79,6 +83,8 @@ pub enum JsonPayloadError {
     Payload(PayloadError),
 }
 
+impl std::error::Error for JsonPayloadError {}
+
 /// Return `BadRequest` for `JsonPayloadError`
 impl ResponseError for JsonPayloadError {
     fn error_response(&self) -> HttpResponse {
@@ -99,6 +105,8 @@ pub enum PathError {
     Deserialize(serde::de::value::Error),
 }
 
+impl std::error::Error for PathError {}
+
 /// Return `BadRequest` for `PathError`
 impl ResponseError for PathError {
     fn status_code(&self) -> StatusCode {
@@ -114,6 +122,8 @@ pub enum QueryPayloadError {
     Deserialize(serde::de::value::Error),
 }
 
+impl std::error::Error for QueryPayloadError {}
+
 /// Return `BadRequest` for `QueryPayloadError`
 impl ResponseError for QueryPayloadError {
     fn status_code(&self) -> StatusCode {
@@ -139,6 +149,8 @@ pub enum ReadlinesError {
     ContentTypeError(ContentTypeError),
 }
 
+impl std::error::Error for ReadlinesError {}
+
 /// Return `BadRequest` for `ReadlinesError`
 impl ResponseError for ReadlinesError {
     fn status_code(&self) -> StatusCode {