diff --git a/ruma-api-macros/src/api.rs b/ruma-api-macros/src/api.rs index 4e2498ac..e40101cc 100644 --- a/ruma-api-macros/src/api.rs +++ b/ruma-api-macros/src/api.rs @@ -101,7 +101,7 @@ impl ToTokens for Api { let request_type = &self.request; let response_type = &self.response; - let request_try_from_type = if self.request.contains_lifetimes() { + let incoming_request_type = if self.request.contains_lifetimes() { quote!(IncomingRequest) } else { quote!(Request) @@ -227,22 +227,25 @@ impl ToTokens for Api { let request_lifetimes = self.request.combine_lifetimes(); - let non_auth_endpoint_impl = if requires_authentication.value { + let non_auth_endpoint_impls = if requires_authentication.value { TokenStream::new() } else { quote! { - impl #request_lifetimes #ruma_api_import::NonAuthEndpoint + impl #request_lifetimes #ruma_api_import::OutgoingNonAuthRequest for Request #request_lifetimes {} + + impl #ruma_api_import::IncomingNonAuthRequest for #incoming_request_type {} } }; let api = quote! { - #[doc = #request_doc] #request_type - impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Request>> for #request_try_from_type { + impl ::std::convert::TryFrom<#ruma_api_import::exports::http::Request>> + for #incoming_request_type + { type Error = #ruma_api_import::error::FromHttpRequestError; #[allow(unused_variables)] @@ -308,21 +311,24 @@ impl ToTokens for Api { } } - impl #request_lifetimes #ruma_api_import::Endpoint for Request #request_lifetimes { - type Response = Response; - type ResponseError = #error; - type IncomingRequest = ::Incoming; + const __METADATA: #ruma_api_import::Metadata = #ruma_api_import::Metadata { + description: #description, + method: #ruma_api_import::exports::http::Method::#method, + name: #name, + path: #path, + rate_limited: #rate_limited, + requires_authentication: #requires_authentication, + }; + + impl #request_lifetimes #ruma_api_import::OutgoingRequest + for Request #request_lifetimes + { + type EndpointError = #error; type IncomingResponse = ::Incoming; + // FIXME: Doc string interpolation /// Metadata for the `#name` endpoint. - const METADATA: #ruma_api_import::Metadata = #ruma_api_import::Metadata { - description: #description, - method: #ruma_api_import::exports::http::Method::#method, - name: #name, - path: #path, - rate_limited: #rate_limited, - requires_authentication: #requires_authentication, - }; + const METADATA: #ruma_api_import::Metadata = __METADATA; #[allow(unused_mut, unused_variables)] fn try_into_http_request( @@ -333,7 +339,7 @@ impl ToTokens for Api { #ruma_api_import::exports::http::Request>, #ruma_api_import::error::IntoHttpError, > { - let metadata = Request::METADATA; + let metadata = ::METADATA; let http_request = #ruma_api_import::exports::http::Request::builder() .method(#ruma_api_import::exports::http::Method::#method) @@ -350,7 +356,16 @@ impl ToTokens for Api { } } - #non_auth_endpoint_impl + impl #ruma_api_import::IncomingRequest for #incoming_request_type { + type EndpointError = #error; + type OutgoingResponse = Response; + + // FIXME: Doc string interpolation + /// Metadata for the `#name` endpoint. + const METADATA: #ruma_api_import::Metadata = __METADATA; + } + + #non_auth_endpoint_impls }; api.to_tokens(tokens); diff --git a/ruma-api/src/error.rs b/ruma-api/src/error.rs index 39cd0025..bb455667 100644 --- a/ruma-api/src/error.rs +++ b/ruma-api/src/error.rs @@ -4,12 +4,14 @@ use std::fmt::{self, Display, Formatter}; +use crate::EndpointError; + // FIXME when `!` becomes stable use it -/// Default `ResponseError` for `ruma_api!` macro +/// Default `EndpointError` for `ruma_api!` macro #[derive(Clone, Copy, Debug)] pub enum Void {} -impl crate::EndpointError for Void { +impl EndpointError for Void { fn try_from_response( response: http::Response>, ) -> Result { diff --git a/ruma-api/src/lib.rs b/ruma-api/src/lib.rs index d5ec67c4..2daa9159 100644 --- a/ruma-api/src/lib.rs +++ b/ruma-api/src/lib.rs @@ -231,7 +231,7 @@ pub trait Outgoing { type Incoming; } -/// Gives users the ability to define their own serializable/deserializable errors. +/// Gives users the ability to define their own serializable / deserializable errors. pub trait EndpointError: std::error::Error + Sized { /// Tries to construct `Self` from an `http::Response`. /// @@ -242,22 +242,15 @@ pub trait EndpointError: std::error::Error + Sized { ) -> Result; } -/// A Matrix API endpoint. -/// -/// The type implementing this trait contains any data needed to make a request to the endpoint. -pub trait Endpoint: Outgoing::IncomingRequest> { - /// Data returned in a successful response from the endpoint. - type Response: Outgoing - + TryInto>, Error = IntoHttpError>; - /// Error type returned when response from endpoint fails. - type ResponseError: EndpointError; +/// A request type for a Matrix API endpoint. (trait used for sending requests) +pub trait OutgoingRequest { + /// A type capturing the expected error conditions the server can return. + type EndpointError: EndpointError; - /// Shorthand for `::Incoming`. - type IncomingRequest: TryFrom>, Error = FromHttpRequestError>; - /// Shorthand for `::Incoming`. + /// Response type returned when the request is successful. type IncomingResponse: TryFrom< http::Response>, - Error = FromHttpResponseError<::ResponseError>, + Error = FromHttpResponseError, >; /// Metadata about the endpoint. @@ -278,11 +271,23 @@ pub trait Endpoint: Outgoing::IncomingRequest> { ) -> Result>, IntoHttpError>; } -/// A Matrix API endpoint that doesn't require authentication. -/// -/// This marker trait is to indicate that a type implementing `Endpoint` doesn't require any -/// authentication. -pub trait NonAuthEndpoint: Endpoint {} +/// A request type for a Matrix API endpoint. (trait used for receiving requests) +pub trait IncomingRequest: TryFrom>, Error = FromHttpRequestError> { + /// A type capturing the error conditions that can be returned in the response. + type EndpointError: EndpointError; + + /// Response type to return when the request is successful. + type OutgoingResponse: TryInto>, Error = IntoHttpError>; + + /// Metadata about the endpoint. + const METADATA: Metadata; +} + +/// Marker trait for requests that don't require authentication. (for the client side) +pub trait OutgoingNonAuthRequest: OutgoingRequest {} + +/// Marker trait for requests that don't require authentication. (for the server side) +pub trait IncomingNonAuthRequest: IncomingRequest {} /// Metadata about an API endpoint. #[derive(Clone, Debug)] diff --git a/ruma-api/tests/conversions.rs b/ruma-api/tests/conversions.rs index 760ab7a6..dd9af77c 100644 --- a/ruma-api/tests/conversions.rs +++ b/ruma-api/tests/conversions.rs @@ -1,6 +1,6 @@ use std::convert::TryFrom; -use ruma_api::{ruma_api, Endpoint as _}; +use ruma_api::{ruma_api, OutgoingRequest as _}; use ruma_identifiers::{user_id, UserId}; ruma_api! { diff --git a/ruma-api/tests/manual_endpoint_impl.rs b/ruma-api/tests/manual_endpoint_impl.rs index 2f1aaf0a..15165257 100644 --- a/ruma-api/tests/manual_endpoint_impl.rs +++ b/ruma-api/tests/manual_endpoint_impl.rs @@ -10,7 +10,7 @@ use ruma_api::{ FromHttpRequestError, FromHttpResponseError, IntoHttpError, RequestDeserializationError, ResponseDeserializationError, ServerError, Void, }, - Endpoint, Metadata, Outgoing, + IncomingRequest, Metadata, Outgoing, OutgoingRequest, }; /// A request to create a new room alias. @@ -24,35 +24,33 @@ impl Outgoing for Request { type Incoming = Self; } -impl Endpoint for Request { - type Response = Response; - type ResponseError = Void; - type IncomingRequest = Self; +const METADATA: Metadata = Metadata { + description: "Add an alias to a room.", + method: Method::PUT, + name: "create_alias", + path: "/_matrix/client/r0/directory/room/:room_alias", + rate_limited: false, + requires_authentication: false, +}; + +impl OutgoingRequest for Request { + type EndpointError = Void; type IncomingResponse = Response; - const METADATA: Metadata = Metadata { - description: "Add an alias to a room.", - method: Method::PUT, - name: "create_alias", - path: "/_matrix/client/r0/directory/room/:room_alias", - rate_limited: false, - requires_authentication: false, - }; + const METADATA: Metadata = METADATA; fn try_into_http_request( self, base_url: &str, _access_token: Option<&str>, ) -> Result>, IntoHttpError> { - let metadata = Request::METADATA; - - let url = (base_url.to_owned() + metadata.path) + let url = (base_url.to_owned() + METADATA.path) .replace(":room_alias", &self.room_alias.to_string()); let request_body = RequestBody { room_id: self.room_id }; let http_request = http::Request::builder() - .method(metadata.method) + .method(METADATA.method) .uri(url) .body(serde_json::to_vec(&request_body)?) // this cannot fail because we don't give user-supplied data to any of the @@ -63,6 +61,13 @@ impl Endpoint for Request { } } +impl IncomingRequest for Request { + type EndpointError = Void; + type OutgoingResponse = Response; + + const METADATA: Metadata = METADATA; +} + impl TryFrom>> for Request { type Error = FromHttpRequestError; diff --git a/ruma-api/tests/no_fields.rs b/ruma-api/tests/no_fields.rs index 38ce16d0..520776f8 100644 --- a/ruma-api/tests/no_fields.rs +++ b/ruma-api/tests/no_fields.rs @@ -1,6 +1,6 @@ use std::convert::TryFrom; -use ruma_api::{ruma_api, Endpoint}; +use ruma_api::{ruma_api, OutgoingRequest as _}; ruma_api! { metadata: { diff --git a/ruma-client-api/src/r0/directory/get_public_rooms.rs b/ruma-client-api/src/r0/directory/get_public_rooms.rs index 5746e24c..85e24e11 100644 --- a/ruma-client-api/src/r0/directory/get_public_rooms.rs +++ b/ruma-client-api/src/r0/directory/get_public_rooms.rs @@ -56,7 +56,7 @@ mod tests { use std::convert::TryInto; use js_int::uint; - use ruma_api::Endpoint as _; + use ruma_api::OutgoingRequest as _; use super::{Request, Response}; diff --git a/ruma-client-api/src/r0/message/get_message_events.rs b/ruma-client-api/src/r0/message/get_message_events.rs index 82d42084..9bd7062e 100644 --- a/ruma-client-api/src/r0/message/get_message_events.rs +++ b/ruma-client-api/src/r0/message/get_message_events.rs @@ -118,7 +118,7 @@ mod tests { use super::{Direction, Request}; use js_int::uint; - use ruma_api::Endpoint; + use ruma_api::OutgoingRequest; use ruma_identifiers::room_id; use crate::r0::filter::{LazyLoadOptions, RoomEventFilter}; diff --git a/ruma-client-api/src/r0/session/login.rs b/ruma-client-api/src/r0/session/login.rs index 191c97b5..e5a75a25 100644 --- a/ruma-client-api/src/r0/session/login.rs +++ b/ruma-client-api/src/r0/session/login.rs @@ -140,7 +140,7 @@ mod user_serde; #[cfg(test)] mod tests { - use ruma_api::Endpoint; + use ruma_api::OutgoingRequest; use serde_json::{from_value as from_json_value, json, Value as JsonValue}; use super::{LoginInfo, Medium, Request, UserInfo}; diff --git a/ruma-client-api/src/r0/sync/sync_events.rs b/ruma-client-api/src/r0/sync/sync_events.rs index 8450fd28..8f62e233 100644 --- a/ruma-client-api/src/r0/sync/sync_events.rs +++ b/ruma-client-api/src/r0/sync/sync_events.rs @@ -403,7 +403,7 @@ impl DeviceLists { mod tests { use std::{convert::TryInto, time::Duration}; - use ruma_api::Endpoint; + use ruma_api::OutgoingRequest; use serde_json::{from_value as from_json_value, json, to_value as to_json_value}; use matches::assert_matches; diff --git a/ruma-client/src/lib.rs b/ruma-client/src/lib.rs index 09beea2d..2a02f809 100644 --- a/ruma-client/src/lib.rs +++ b/ruma-client/src/lib.rs @@ -113,7 +113,7 @@ use http::{uri::Uri, Response as HttpResponse}; use hyper::{client::HttpConnector, Client as HyperClient}; #[cfg(feature = "hyper-tls")] use hyper_tls::HttpsConnector; -use ruma_api::Endpoint; +use ruma_api::OutgoingRequest; use ruma_client_api::r0::sync::sync_events::{ Filter as SyncFilter, Request as SyncRequest, Response as SyncResponse, }; @@ -350,19 +350,19 @@ where } /// Makes a request to a Matrix API endpoint. - pub async fn request( + pub async fn request( &self, request: Request, - ) -> Result> { + ) -> Result> { self.request_with_url_params(request, None).await } /// Makes a request to a Matrix API endpoint including additional URL parameters. - pub async fn request_with_url_params( + pub async fn request_with_url_params( &self, request: Request, extra_params: Option>, - ) -> Result> { + ) -> Result> { let client = self.0.clone(); let mut http_request = { let session;