From d36f82faeb6b0290888edb201a0188ead603d4cc Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Tue, 22 Sep 2020 01:48:45 +0200 Subject: [PATCH] api: Use thiserror to derive many Display + Error implementations --- ruma-api/Cargo.toml | 1 + ruma-api/src/error.rs | 180 +++++++++++------------------------------- ruma-api/src/lib.rs | 2 +- 3 files changed, 47 insertions(+), 136 deletions(-) diff --git a/ruma-api/Cargo.toml b/ruma-api/Cargo.toml index 372f9ee2..56e3c31e 100644 --- a/ruma-api/Cargo.toml +++ b/ruma-api/Cargo.toml @@ -24,6 +24,7 @@ ruma-serde = { version = "0.2.3", path = "../ruma-serde" } serde = { version = "1.0.114", features = ["derive"] } serde_json = "1.0.57" strum = "0.19.2" +thiserror = "1.0.20" [dev-dependencies] ruma-common = { version = "0.2.0", path = "../ruma-common" } diff --git a/ruma-api/src/error.rs b/ruma-api/src/error.rs index 04563ceb..9a30ddc2 100644 --- a/ruma-api/src/error.rs +++ b/ruma-api/src/error.rs @@ -4,9 +4,11 @@ use std::{ error::Error as StdError, - fmt::{self, Display, Formatter}, + fmt::{self, Debug, Display, Formatter}, }; +use thiserror::Error; + use crate::EndpointError; // FIXME when `!` becomes stable use it @@ -32,90 +34,45 @@ impl StdError for Void {} /// An error when converting one of ruma's endpoint-specific request or response /// types to the corresponding http type. -#[derive(Debug)] +#[derive(Debug, Error)] #[non_exhaustive] pub enum IntoHttpError { /// Tried to create an authentication request without an access token. + #[error( + "This endpoint has to be converted to http::Request using \ + try_into_authenticated_http_request" + )] NeedsAuthentication, + /// JSON serialization failed. - Json(serde_json::Error), + #[error("JSON serialization failed: {0}")] + Json(#[from] serde_json::Error), + /// Query parameter serialization failed. - Query(ruma_serde::urlencoded::ser::Error), + #[error("Query parameter serialization failed: {0}")] + Query(#[from] ruma_serde::urlencoded::ser::Error), + /// Header serialization failed. - Header(http::header::InvalidHeaderValue), + #[error("Header serialization failed: {0}")] + Header(#[from] http::header::InvalidHeaderValue), + /// HTTP request construction failed. - Http(http::Error), + #[error("HTTP request construction failed: {0}")] + Http(#[from] http::Error), } -impl From for IntoHttpError { - fn from(err: serde_json::Error) -> Self { - Self::Json(err) - } -} - -impl From for IntoHttpError { - fn from(err: ruma_serde::urlencoded::ser::Error) -> Self { - Self::Query(err) - } -} - -impl From for IntoHttpError { - fn from(err: http::header::InvalidHeaderValue) -> Self { - Self::Header(err) - } -} - -impl From for IntoHttpError { - fn from(err: http::Error) -> Self { - Self::Http(err) - } -} - -impl Display for IntoHttpError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match &self { - Self::NeedsAuthentication => write!( - f, - "This endpoint has to be converted to http::Request using \ - try_into_authenticated_http_request" - ), - Self::Json(err) => write!(f, "JSON serialization failed: {}", err), - Self::Query(err) => write!(f, "Query parameter serialization failed: {}", err), - Self::Header(err) => write!(f, "Header serialization failed: {}", err), - Self::Http(err) => write!(f, "HTTP request construction failed: {}", err), - } - } -} - -impl StdError for IntoHttpError {} - -/// An error when converting a http request to one of ruma's endpoint-specific -/// request types. -#[derive(Debug)] +/// An error when converting a http request to one of ruma's endpoint-specific request types. +#[derive(Debug, Error)] #[non_exhaustive] pub enum FromHttpRequestError { /// Deserialization failed - Deserialization(RequestDeserializationError), + #[error("deserialization failed: {0}")] + Deserialization(#[from] RequestDeserializationError), } -impl Display for FromHttpRequestError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - Self::Deserialization(err) => write!(f, "deserialization failed: {}", err), - } - } -} - -impl From for FromHttpRequestError { - fn from(err: RequestDeserializationError) -> Self { - Self::Deserialization(err) - } -} - -impl StdError for FromHttpRequestError {} - /// An error that occurred when trying to deserialize a request. -#[derive(Debug)] +#[derive(Debug, Error)] +#[error("{inner}")] pub struct RequestDeserializationError { inner: DeserializationError, http_request: http::Request>, @@ -132,16 +89,7 @@ impl RequestDeserializationError { } } -impl Display for RequestDeserializationError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - Display::fmt(&self.inner, f) - } -} - -impl StdError for RequestDeserializationError {} - -/// An error when converting a http response to one of ruma's endpoint-specific -/// response types. +/// An error when converting a http response to one of Ruma's endpoint-specific response types. #[derive(Debug)] #[non_exhaustive] pub enum FromHttpResponseError { @@ -232,70 +180,32 @@ impl StdError for ServerError {} /// An error when converting a http request / response to one of ruma's endpoint-specific request / /// response types. -#[derive(Debug)] +#[derive(Debug, Error)] #[non_exhaustive] pub enum DeserializationError { /// Encountered invalid UTF-8. - Utf8(std::str::Utf8Error), + #[error("{0}")] + Utf8(#[from] std::str::Utf8Error), + /// JSON deserialization failed. - Json(serde_json::Error), + #[error("{0}")] + Json(#[from] serde_json::Error), + /// Query parameter deserialization failed. - Query(ruma_serde::urlencoded::de::Error), + #[error("{0}")] + Query(#[from] ruma_serde::urlencoded::de::Error), + /// Got an invalid identifier. - Ident(ruma_identifiers::Error), + #[error("{0}")] + Ident(#[from] ruma_identifiers::Error), + /// Path segment deserialization failed. - Strum(strum::ParseError), + #[error("{0}")] + Strum(#[from] strum::ParseError), + /// Header value deserialization failed. - Header(http::header::ToStrError), -} - -impl Display for DeserializationError { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - DeserializationError::Utf8(err) => Display::fmt(err, f), - DeserializationError::Json(err) => Display::fmt(err, f), - DeserializationError::Query(err) => Display::fmt(err, f), - DeserializationError::Ident(err) => Display::fmt(err, f), - DeserializationError::Strum(err) => Display::fmt(err, f), - DeserializationError::Header(err) => Display::fmt(err, f), - } - } -} - -impl From for DeserializationError { - fn from(err: http::header::ToStrError) -> Self { - Self::Header(err) - } -} - -impl From for DeserializationError { - fn from(err: std::str::Utf8Error) -> Self { - Self::Utf8(err) - } -} - -impl From for DeserializationError { - fn from(err: serde_json::Error) -> Self { - Self::Json(err) - } -} - -impl From for DeserializationError { - fn from(err: ruma_serde::urlencoded::de::Error) -> Self { - Self::Query(err) - } -} - -impl From for DeserializationError { - fn from(err: ruma_identifiers::Error) -> Self { - Self::Ident(err) - } -} - -impl From for DeserializationError { - fn from(err: strum::ParseError) -> Self { - Self::Strum(err) - } + #[error("{0}")] + Header(#[from] http::header::ToStrError), } impl From for DeserializationError { diff --git a/ruma-api/src/lib.rs b/ruma-api/src/lib.rs index c35056b8..efa8431d 100644 --- a/ruma-api/src/lib.rs +++ b/ruma-api/src/lib.rs @@ -236,7 +236,7 @@ pub trait Outgoing { } /// Gives users the ability to define their own serializable / deserializable errors. -pub trait EndpointError: StdError + Sized { +pub trait EndpointError: StdError + Sized + 'static { /// Tries to construct `Self` from an `http::Response`. /// /// This will always return `Err` variant when no `error` field is defined in