From b886de1afc0b90d7ca27db9d5c7dabddbe3d7ee0 Mon Sep 17 00:00:00 2001
From: Martin Fischer <martin@push-f.com>
Date: Wed, 20 Jan 2021 11:41:03 +0100
Subject: introduce Error::Simple and Error::Response

bump version to 0.2.2
---
 src/error.rs   | 55 ++++++++++++++++++++++++++++++++++---------------------
 src/lib.rs     |  2 +-
 src/request.rs |  8 ++++----
 3 files changed, 39 insertions(+), 26 deletions(-)

(limited to 'src')

diff --git a/src/error.rs b/src/error.rs
index 5f35da2..fe998d0 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,55 +1,68 @@
-use std::fmt::Display;
+//! Provides the [`crate::Error`] type.
 
+use thiserror::Error;
 use hyper::StatusCode;
 
 /// Encapsulates a status code and an error message.
-///
-/// All client errors in [`crate::request`] implement [`Into<Error>`].
-#[derive(Debug)]
-pub struct Error {
+#[derive(Error, Debug)]
+#[error("SimpleError({code}, {message})")]
+pub struct SimpleError {
     pub code: StatusCode,
     pub message: String,
 }
 
-impl Display for Error {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "error: {}", self.message)
+impl SimpleError {
+    /// Returns an HTTP response builder with the status code set to `self.code`.
+    pub fn response_builder(&self) -> hyper::http::response::Builder {
+        hyper::Response::builder().status(self.code)
     }
 }
 
-impl std::error::Error for Error {
+/// Error type for request handlers.
+///
+/// All client errors in [`crate::request`] implement [`Into<Error::Simple>`].
+#[derive(Error, Debug)]
+pub enum Error {
+    #[error("SimpleError({}, {})", .0.code, .0.message)]
+    Simple(#[from] SimpleError),
+
+    #[error("ResponseError({})", .0.status())]
+    Response(hyper::Response<hyper::Body>),
 }
 
 impl Error {
-    /// Returns an HTTP response builder with the status code set to `self.code`.
-    pub fn response_builder(&self) -> hyper::http::response::Builder {
-        hyper::Response::builder().status(self.code)
-    }
+    // some convenience methods
 
-    // some conventient constructors for common errors
+    pub fn simple(code: StatusCode, message: String) -> Self {
+        Error::Simple(SimpleError{code, message})
+    }
 
     pub fn bad_request(message: String) -> Self {
-        Error{code: StatusCode::BAD_REQUEST, message}
+        Error::Simple(SimpleError{code: StatusCode::BAD_REQUEST, message})
     }
+
     pub fn not_found(message: String) -> Self {
-        Error{code: StatusCode::NOT_FOUND, message}
+        Error::Simple(SimpleError{code: StatusCode::NOT_FOUND, message})
     }
+
     pub fn unauthorized(message: String) -> Self {
-        Error{code: StatusCode::UNAUTHORIZED, message}
+        Error::Simple(SimpleError{code: StatusCode::UNAUTHORIZED, message})
     }
+
     pub fn internal(message: String) -> Self {
-        Error{code: StatusCode::INTERNAL_SERVER_ERROR, message}
+        Error::Simple(SimpleError{code: StatusCode::INTERNAL_SERVER_ERROR, message})
     }
+
     pub fn method_not_allowed(message: String) -> Self {
-        Error{code: StatusCode::METHOD_NOT_ALLOWED, message}
+        Error::Simple(SimpleError{code: StatusCode::METHOD_NOT_ALLOWED, message})
     }
 }
 
-macro_rules! impl_into_http_error {
+macro_rules! impl_into_error_simple {
     ($type:ident, $status:expr) => {
        impl From<$type> for crate::error::Error {
             fn from(err: $type) -> Self {
-                Self{code: $status, message: format!("{}", err)}
+                Self::Simple(crate::error::SimpleError{code: $status, message: format!("{}", err)})
             }
        }
     };
diff --git a/src/lib.rs b/src/lib.rs
index 63b372b..391eb2c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,7 +4,7 @@ pub use error::Error;
 pub use mime;
 pub use httpdate;
 
-#[macro_use] mod error;
+#[macro_use] pub mod error;
 pub mod security;
 pub mod request;
 pub mod response;
diff --git a/src/request.rs b/src/request.rs
index 79ca2ae..c874ab5 100644
--- a/src/request.rs
+++ b/src/request.rs
@@ -169,12 +169,12 @@ pub mod error {
     #[derive(Error, Debug)]
     #[error("query deserialize error: {0}")]
     pub struct QueryError(pub serde_urlencoded::de::Error);
-    impl_into_http_error!(QueryError, StatusCode::BAD_REQUEST);
+    impl_into_error_simple!(QueryError, StatusCode::BAD_REQUEST);
 
     #[derive(Error, Debug)]
     #[error("failed to read body")]
     pub struct BodyError(pub hyper::Error);
-    impl_into_http_error!(BodyError, StatusCode::BAD_REQUEST);
+    impl_into_error_simple!(BodyError, StatusCode::BAD_REQUEST);
 
     #[derive(Error, Debug)]
     #[error("expected Content-Type {expected} but received {}", received.as_ref().unwrap_or(&"nothing".to_owned()))]
@@ -194,7 +194,7 @@ pub mod error {
         #[error("form deserialize error: {0}")]
         Deserialize(#[from] serde_urlencoded::de::Error),
     }
-    impl_into_http_error!(FormError, StatusCode::BAD_REQUEST);
+    impl_into_error_simple!(FormError, StatusCode::BAD_REQUEST);
 
     #[derive(Error, Debug)]
     pub enum CsrfProtectedFormError {
@@ -213,5 +213,5 @@ pub mod error {
         #[error("{0}")]
         Csrf(#[from] CsrfError),
     }
-    impl_into_http_error!(CsrfProtectedFormError, StatusCode::BAD_REQUEST);
+    impl_into_error_simple!(CsrfProtectedFormError, StatusCode::BAD_REQUEST);
 }
\ No newline at end of file
-- 
cgit v1.2.3