api: Replace error::Void by error::MatrixError

This commit is contained in:
Jonas Platte 2021-05-08 14:33:12 +02:00
parent c01e8340eb
commit a0f7e1b771
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
8 changed files with 57 additions and 46 deletions

View File

@ -52,8 +52,8 @@ pub mod some_endpoint {
pub value: String, pub value: String,
} }
// An error can also be specified or defaults to `ruma_api::error::Void`. // An error can also be specified or defaults to `ruma_api::error::MatrixError`.
error: ruma_api::Error error: crate::Error
} }
} }
``` ```

View File

@ -63,8 +63,9 @@ pub fn expand_all(api: Api) -> syn::Result<TokenStream> {
}) })
.collect(); .collect();
let error_ty = let error_ty = api
api.error_ty.map_or_else(|| quote! { #ruma_api::error::Void }, |err_ty| quote! { #err_ty }); .error_ty
.map_or_else(|| quote! { #ruma_api::error::MatrixError }, |err_ty| quote! { #err_ty });
let request = api.request.map(|req| req.expand(metadata, &error_ty, &ruma_api)); let request = api.request.map(|req| req.expand(metadata, &error_ty, &ruma_api));
let response = api.response.map(|res| res.expand(metadata, &error_ty, &ruma_api)); let response = api.response.map(|res| res.expand(metadata, &error_ty, &ruma_api));

View File

@ -12,10 +12,14 @@ Breaking changes:
* Endpoint authentication is now more granularly defined by an enum `AuthScheme` * Endpoint authentication is now more granularly defined by an enum `AuthScheme`
instead of a boolean. The `ruma_api!` macro has been updated to require instead of a boolean. The `ruma_api!` macro has been updated to require
`authentication` instead of `requires_authentication`. `authentication` instead of `requires_authentication`.
* Remove `error::Void`, the default error type for `ruma_api!` is now `error::MatrixError`
(see below)
Improvements: Improvements:
* The `EndpointError`s that come with ruma crates now implement `std::errror::Error`. * The `EndpointError`s that come with ruma crates now implement `std::errror::Error`
* Add a new `MatrixError` type to the `error` module that consists of a HTTP status code and JSON
`body` and is the new default error type for `ruma_api!`
# 0.16.1 # 0.16.1

View File

@ -5,39 +5,55 @@
use std::{error::Error as StdError, fmt}; use std::{error::Error as StdError, fmt};
use bytes::BufMut; use bytes::BufMut;
use serde_json::{from_slice as from_json_slice, Value as JsonValue};
use thiserror::Error; use thiserror::Error;
use crate::{EndpointError, OutgoingResponse}; use crate::{EndpointError, OutgoingResponse};
// FIXME when `!` becomes stable use it /// A general-purpose Matrix error type consisting of an HTTP status code and a JSON body.
/// Default `EndpointError` for `ruma_api!` macro ///
#[derive(Clone, Copy, Debug)] /// Note that individual `ruma-*-api` crates may provide more specific error types.
pub enum Void {} #[derive(Clone, Debug)]
pub struct MatrixError {
/// The http reponse's status code.
pub status_code: http::StatusCode,
impl OutgoingResponse for Void { /// The http response's body.
pub body: JsonValue,
}
impl fmt::Display for MatrixError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[{}] ", self.status_code.as_u16())?;
fmt::Display::fmt(&self.body, f)
}
}
impl StdError for MatrixError {}
impl OutgoingResponse for MatrixError {
fn try_into_http_response<T: Default + BufMut>( fn try_into_http_response<T: Default + BufMut>(
self, self,
) -> Result<http::Response<T>, IntoHttpError> { ) -> Result<http::Response<T>, IntoHttpError> {
match self {} http::Response::builder()
.header(http::header::CONTENT_TYPE, "application/json")
.status(self.status_code)
.body(ruma_serde::json_to_buf(&self.body)?)
.map_err(Into::into)
} }
} }
impl EndpointError for Void { impl EndpointError for MatrixError {
fn try_from_http_response<T: AsRef<[u8]>>( fn try_from_http_response<T: AsRef<[u8]>>(
_response: http::Response<T>, response: http::Response<T>,
) -> Result<Self, ResponseDeserializationError> { ) -> Result<Self, ResponseDeserializationError> {
Err(ResponseDeserializationError::none()) Ok(Self {
status_code: response.status(),
body: from_json_slice(response.body().as_ref())?,
})
} }
} }
impl fmt::Display for Void {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {}
}
}
impl StdError for Void {}
/// An error when converting one of ruma's endpoint-specific request or response /// An error when converting one of ruma's endpoint-specific request or response
/// types to the corresponding http type. /// types to the corresponding http type.
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -150,13 +166,7 @@ impl<E: StdError> StdError for FromHttpResponseError<E> {}
/// An error that occurred when trying to deserialize a response. /// An error that occurred when trying to deserialize a response.
#[derive(Debug)] #[derive(Debug)]
pub struct ResponseDeserializationError { pub struct ResponseDeserializationError {
inner: Option<DeserializationError>, inner: DeserializationError,
}
impl ResponseDeserializationError {
fn none() -> Self {
Self { inner: None }
}
} }
impl<T> From<T> for ResponseDeserializationError impl<T> From<T> for ResponseDeserializationError
@ -164,17 +174,13 @@ where
T: Into<DeserializationError>, T: Into<DeserializationError>,
{ {
fn from(err: T) -> Self { fn from(err: T) -> Self {
Self { inner: Some(err.into()) } Self { inner: err.into() }
} }
} }
impl fmt::Display for ResponseDeserializationError { impl fmt::Display for ResponseDeserializationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(ref inner) = self.inner { fmt::Display::fmt(&self.inner, f)
fmt::Display::fmt(inner, f)
} else {
fmt::Display::fmt("deserialization error, no error specified", f)
}
} }
} }

View File

@ -49,7 +49,7 @@ use ruma_identifiers::UserId;
/// // in the response from this API endpoint. /// // in the response from this API endpoint.
/// } /// }
/// ///
/// // The error returned when a response fails, defaults to `Void`. /// // The error returned when a response fails, defaults to `MatrixError`.
/// error: path::to::Error /// error: path::to::Error
/// } /// }
/// ``` /// ```

View File

@ -5,7 +5,7 @@ use std::convert::TryFrom;
use bytes::BufMut; use bytes::BufMut;
use http::{header::CONTENT_TYPE, method::Method}; use http::{header::CONTENT_TYPE, method::Method};
use ruma_api::{ use ruma_api::{
error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, ServerError, Void}, error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, MatrixError, ServerError},
AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest, AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest,
OutgoingResponse, SendAccessToken, OutgoingResponse, SendAccessToken,
}; };
@ -34,7 +34,7 @@ const METADATA: Metadata = Metadata {
}; };
impl OutgoingRequest for Request { impl OutgoingRequest for Request {
type EndpointError = Void; type EndpointError = MatrixError;
type IncomingResponse = Response; type IncomingResponse = Response;
const METADATA: Metadata = METADATA; const METADATA: Metadata = METADATA;
@ -62,7 +62,7 @@ impl OutgoingRequest for Request {
} }
impl IncomingRequest for Request { impl IncomingRequest for Request {
type EndpointError = Void; type EndpointError = MatrixError;
type OutgoingResponse = Response; type OutgoingResponse = Response;
const METADATA: Metadata = METADATA; const METADATA: Metadata = METADATA;
@ -98,16 +98,16 @@ impl Outgoing for Response {
} }
impl IncomingResponse for Response { impl IncomingResponse for Response {
type EndpointError = Void; type EndpointError = MatrixError;
fn try_from_http_response<T: AsRef<[u8]>>( fn try_from_http_response<T: AsRef<[u8]>>(
http_response: http::Response<T>, http_response: http::Response<T>,
) -> Result<Self, FromHttpResponseError<Void>> { ) -> Result<Self, FromHttpResponseError<MatrixError>> {
if http_response.status().as_u16() < 400 { if http_response.status().as_u16() < 400 {
Ok(Response) Ok(Response)
} else { } else {
Err(FromHttpResponseError::Http(ServerError::Known( Err(FromHttpResponseError::Http(ServerError::Known(
<Void as EndpointError>::try_from_http_response(http_response)?, <MatrixError as EndpointError>::try_from_http_response(http_response)?,
))) )))
} }
} }

View File

@ -1,6 +1,6 @@
use bytes::BufMut; use bytes::BufMut;
use ruma_api::{ use ruma_api::{
error::{FromHttpResponseError, IntoHttpError, Void}, error::{FromHttpResponseError, IntoHttpError, MatrixError},
ruma_api, IncomingResponse, OutgoingResponse, ruma_api, IncomingResponse, OutgoingResponse,
}; };
use ruma_serde::Outgoing; use ruma_serde::Outgoing;
@ -26,11 +26,11 @@ ruma_api! {
pub struct Response; pub struct Response;
impl IncomingResponse for Response { impl IncomingResponse for Response {
type EndpointError = Void; type EndpointError = MatrixError;
fn try_from_http_response<T: AsRef<[u8]>>( fn try_from_http_response<T: AsRef<[u8]>>(
_: http::Response<T>, _: http::Response<T>,
) -> Result<Self, FromHttpResponseError<Void>> { ) -> Result<Self, FromHttpResponseError<MatrixError>> {
todo!() todo!()
} }
} }

View File

@ -15,7 +15,7 @@ ruma_api! {
response: {} response: {}
#[derive(Default)] #[derive(Default)]
error: ruma_api::error::Void error: ruma_api::error::MatrixError
} }
fn main() {} fn main() {}