diff --git a/ruma-api-macros/src/api/request/incoming.rs b/ruma-api-macros/src/api/request/incoming.rs index cfb8828a..e68a599b 100644 --- a/ruma-api-macros/src/api/request/incoming.rs +++ b/ruma-api-macros/src/api/request/incoming.rs @@ -10,7 +10,6 @@ impl Request { error_ty: &TokenStream, ruma_api: &TokenStream, ) -> TokenStream { - let bytes = quote! { #ruma_api::exports::bytes }; let http = quote! { #ruma_api::exports::http }; let percent_encoding = quote! { #ruma_api::exports::percent_encoding }; let ruma_serde = quote! { #ruma_api::exports::ruma_serde }; @@ -159,15 +158,17 @@ impl Request { RequestBody #body_lifetimes as #ruma_serde::Outgoing >::Incoming = { - let body = request.into_body(); - if #bytes::Buf::has_remaining(&body) { - #serde_json::from_reader(#bytes::Buf::reader(body))? - } else { + let body = ::std::convert::AsRef::<[::std::primitive::u8]>::as_ref( + request.body(), + ); + + #serde_json::from_slice(match body { // If the request body is completely empty, pretend it is an empty JSON // object instead. This allows requests with only optional body parameters // to be deserialized in that case. - #serde_json::from_str("{}")? - } + [] => b"{}", + b => b, + })? }; } } else { @@ -184,13 +185,8 @@ impl Request { } else if let Some(field) = self.newtype_raw_body_field() { let field_name = field.ident.as_ref().expect("expected field to have an identifier"); let parse = quote! { - let #field_name = { - let mut reader = #bytes::Buf::reader(request.into_body()); - let mut vec = ::std::vec::Vec::new(); - ::std::io::Read::read_to_end(&mut reader, &mut vec) - .expect("reading from a bytes::Buf never fails"); - vec - }; + let #field_name = + ::std::convert::AsRef::<[u8]>::as_ref(request.body()).to_vec(); }; (parse, quote! { #field_name, }) diff --git a/ruma-api-macros/src/api/response/incoming.rs b/ruma-api-macros/src/api/response/incoming.rs index daf98857..4353cc4b 100644 --- a/ruma-api-macros/src/api/response/incoming.rs +++ b/ruma-api-macros/src/api/response/incoming.rs @@ -5,7 +5,6 @@ use super::{Response, ResponseField}; impl Response { pub fn expand_incoming(&self, error_ty: &TokenStream, ruma_api: &TokenStream) -> TokenStream { - let bytes = quote! { #ruma_api::exports::bytes }; let http = quote! { #ruma_api::exports::http }; let ruma_serde = quote! { #ruma_api::exports::ruma_serde }; let serde_json = quote! { #ruma_api::exports::serde_json }; @@ -25,15 +24,17 @@ impl Response { ResponseBody as #ruma_serde::Outgoing >::Incoming = { - let body = response.into_body(); - if #bytes::Buf::has_remaining(&body) { - #serde_json::from_reader(#bytes::Buf::reader(body))? - } else { + let body = ::std::convert::AsRef::<[::std::primitive::u8]>::as_ref( + response.body(), + ); + + #serde_json::from_slice(match body { // If the response body is completely empty, pretend it is an empty // JSON object instead. This allows responses with only optional body // parameters to be deserialized in that case. - #serde_json::from_str("{}")? - } + [] => b"{}", + b => b, + })? }; } } else { @@ -93,11 +94,10 @@ impl Response { ResponseField::NewtypeRawBody(_) => { new_type_raw_body = Some(quote! { #field_name: { - let mut reader = #bytes::Buf::reader(response.into_body()); - let mut vec = ::std::vec::Vec::new(); - ::std::io::Read::read_to_end(&mut reader, &mut vec) - .expect("reading from a bytes::Buf never fails"); - vec + ::std::convert::AsRef::<[::std::primitive::u8]>::as_ref( + response.body(), + ) + .to_vec() } }); // skip adding to the vec @@ -120,7 +120,7 @@ impl Response { impl #ruma_api::IncomingResponse for Response { type EndpointError = #error_ty; - fn try_from_http_response( + fn try_from_http_response>( response: #http::Response, ) -> ::std::result::Result< Self, @@ -130,15 +130,17 @@ impl Response { #extract_response_headers #typed_response_body_decl - Ok(Self { + ::std::result::Result::Ok(Self { #response_init_fields }) } else { match <#error_ty as #ruma_api::EndpointError>::try_from_http_response( response ) { - Ok(err) => Err(#ruma_api::error::ServerError::Known(err).into()), - Err(response_err) => { + ::std::result::Result::Ok(err) => { + Err(#ruma_api::error::ServerError::Known(err).into()) + } + ::std::result::Result::Err(response_err) => { Err(#ruma_api::error::ServerError::Unknown(response_err).into()) } } diff --git a/ruma-api/Cargo.toml b/ruma-api/Cargo.toml index 39c4689c..4e539f10 100644 --- a/ruma-api/Cargo.toml +++ b/ruma-api/Cargo.toml @@ -19,7 +19,6 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -bytes = "1.0.1" http = "0.2.2" percent-encoding = "2.1.0" ruma-api-macros = { version = "=0.17.0-alpha.2", path = "../ruma-api-macros" } diff --git a/ruma-api/src/error.rs b/ruma-api/src/error.rs index 8b8cc13e..154c3d42 100644 --- a/ruma-api/src/error.rs +++ b/ruma-api/src/error.rs @@ -4,7 +4,6 @@ use std::{error::Error as StdError, fmt}; -use bytes::Buf; use thiserror::Error; use crate::{EndpointError, OutgoingResponse}; @@ -21,7 +20,7 @@ impl OutgoingResponse for Void { } impl EndpointError for Void { - fn try_from_http_response( + fn try_from_http_response>( _response: http::Response, ) -> Result { Err(ResponseDeserializationError::none()) diff --git a/ruma-api/src/lib.rs b/ruma-api/src/lib.rs index 02e3890e..3baddcdf 100644 --- a/ruma-api/src/lib.rs +++ b/ruma-api/src/lib.rs @@ -22,7 +22,6 @@ compile_error!("ruma_api's Cargo features only exist as a workaround are not mea use std::{convert::TryInto as _, error::Error as StdError}; -use bytes::Buf; use http::Method; use ruma_identifiers::UserId; @@ -204,7 +203,6 @@ pub mod error; /// It is not considered part of ruma-api's public API. #[doc(hidden)] pub mod exports { - pub use bytes; pub use http; pub use percent_encoding; pub use ruma_serde; @@ -246,7 +244,7 @@ pub trait IncomingResponse: Sized { type EndpointError: EndpointError; /// Tries to convert the given `http::Response` into this response type. - fn try_from_http_response( + fn try_from_http_response>( response: http::Response, ) -> Result>; } @@ -301,7 +299,9 @@ pub trait IncomingRequest: Sized { const METADATA: Metadata; /// Tries to turn the given `http::Request` into this request type. - fn try_from_http_request(req: http::Request) -> Result; + fn try_from_http_request>( + req: http::Request, + ) -> Result; } /// A request type for a Matrix API endpoint, used for sending responses. @@ -319,7 +319,7 @@ pub trait EndpointError: OutgoingResponse + StdError + Sized + 'static { /// /// This will always return `Err` variant when no `error` field is defined in /// the `ruma_api` macro. - fn try_from_http_response( + fn try_from_http_response>( response: http::Response, ) -> Result; } diff --git a/ruma-api/tests/conversions.rs b/ruma-api/tests/conversions.rs index 144aaad3..3d9a9e4f 100644 --- a/ruma-api/tests/conversions.rs +++ b/ruma-api/tests/conversions.rs @@ -48,7 +48,7 @@ fn request_serde() { }; let http_req = req.clone().try_into_http_request("https://homeserver.tld", None).unwrap(); - let req2 = Request::try_from_http_request(http_req.map(std::io::Cursor::new)).unwrap(); + let req2 = Request::try_from_http_request(http_req).unwrap(); assert_eq!(req.hello, req2.hello); assert_eq!(req.world, req2.world); diff --git a/ruma-api/tests/manual_endpoint_impl.rs b/ruma-api/tests/manual_endpoint_impl.rs index d28b9e63..0e25dca2 100644 --- a/ruma-api/tests/manual_endpoint_impl.rs +++ b/ruma-api/tests/manual_endpoint_impl.rs @@ -2,7 +2,6 @@ use std::convert::TryFrom; -use bytes::Buf; use http::{header::CONTENT_TYPE, method::Method}; use ruma_api::{ error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, ServerError, Void}, @@ -67,7 +66,7 @@ impl IncomingRequest for Request { const METADATA: Metadata = METADATA; - fn try_from_http_request( + fn try_from_http_request>( request: http::Request, ) -> Result { let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect(); @@ -78,7 +77,7 @@ impl IncomingRequest for Request { TryFrom::try_from(&*decoded)? }; - let request_body: RequestBody = serde_json::from_reader(request.into_body().reader())?; + let request_body: RequestBody = serde_json::from_slice(request.body().as_ref())?; Ok(Request { room_id: request_body.room_id, room_alias }) } @@ -100,7 +99,7 @@ impl Outgoing for Response { impl IncomingResponse for Response { type EndpointError = Void; - fn try_from_http_response( + fn try_from_http_response>( http_response: http::Response, ) -> Result> { if http_response.status().as_u16() < 400 { diff --git a/ruma-api/tests/ui/05-request-only.rs b/ruma-api/tests/ui/05-request-only.rs index 49af1b29..9e01fc95 100644 --- a/ruma-api/tests/ui/05-request-only.rs +++ b/ruma-api/tests/ui/05-request-only.rs @@ -1,4 +1,3 @@ -use bytes::Buf; use ruma_api::{ error::{FromHttpResponseError, IntoHttpError, Void}, ruma_api, IncomingResponse, OutgoingResponse, @@ -28,7 +27,7 @@ pub struct Response; impl IncomingResponse for Response { type EndpointError = Void; - fn try_from_http_response( + fn try_from_http_response>( _: http::Response, ) -> Result> { todo!() diff --git a/ruma-client-api/Cargo.toml b/ruma-client-api/Cargo.toml index 7b4b4408..0bb3f149 100644 --- a/ruma-client-api/Cargo.toml +++ b/ruma-client-api/Cargo.toml @@ -17,7 +17,6 @@ edition = "2018" [dependencies] assign = "1.1.1" -bytes = "1.0.1" http = "0.2.2" js_int = { version = "0.2.0", features = ["serde"] } maplit = "1.0.2" diff --git a/ruma-client-api/src/error.rs b/ruma-client-api/src/error.rs index b1b8996f..f0e599e1 100644 --- a/ruma-client-api/src/error.rs +++ b/ruma-client-api/src/error.rs @@ -2,14 +2,13 @@ use std::{collections::BTreeMap, fmt, time::Duration}; -use bytes::Buf; use ruma_api::{ error::{IntoHttpError, ResponseDeserializationError}, EndpointError, OutgoingResponse, }; use ruma_identifiers::RoomVersionId; use serde::{Deserialize, Serialize}; -use serde_json::{from_reader as from_json_reader, to_vec as to_json_vec, Value as JsonValue}; +use serde_json::{from_slice as from_json_slice, to_vec as to_json_vec, Value as JsonValue}; /// Deserialize and Serialize implementations for ErrorKind. /// Separate module because it's a lot of code. @@ -206,11 +205,11 @@ pub struct Error { } impl EndpointError for Error { - fn try_from_http_response( + fn try_from_http_response>( response: http::Response, ) -> Result { let status = response.status(); - let error_body: ErrorBody = from_json_reader(response.into_body().reader())?; + let error_body: ErrorBody = from_json_slice(response.body().as_ref())?; Ok(error_body.into_error(status)) } } diff --git a/ruma-client-api/src/r0/message/send_message_event.rs b/ruma-client-api/src/r0/message/send_message_event.rs index 832143db..aba490af 100644 --- a/ruma-client-api/src/r0/message/send_message_event.rs +++ b/ruma-client-api/src/r0/message/send_message_event.rs @@ -104,7 +104,7 @@ impl ruma_api::IncomingRequest for IncomingRequest { const METADATA: ruma_api::Metadata = METADATA; - fn try_from_http_request( + fn try_from_http_request>( request: http::Request, ) -> Result { use std::convert::TryFrom; @@ -129,7 +129,7 @@ impl ruma_api::IncomingRequest for IncomingRequest { let content = { let event_type = percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()?; - let body: Box = serde_json::from_reader(body.reader())?; + let body: Box = serde_json::from_slice(body.as_ref())?; AnyMessageEventContent::from_parts(&event_type, body)? }; diff --git a/ruma-client-api/src/r0/profile/set_avatar_url.rs b/ruma-client-api/src/r0/profile/set_avatar_url.rs index 0013e433..e877bead 100644 --- a/ruma-client-api/src/r0/profile/set_avatar_url.rs +++ b/ruma-client-api/src/r0/profile/set_avatar_url.rs @@ -77,9 +77,8 @@ mod tests { http::Request::builder() .method("PUT") .uri("https://bar.org/_matrix/client/r0/profile/@foo:bar.org/avatar_url") - .body(std::io::Cursor::new( - serde_json::to_vec(&serde_json::json!({ "avatar_url": "" })).unwrap(), - )).unwrap(), + .body(serde_json::to_vec(&serde_json::json!({ "avatar_url": "" })).unwrap()) + .unwrap(), ).unwrap(), IncomingRequest { user_id, avatar_url: None } if user_id == "@foo:bar.org" ); diff --git a/ruma-client-api/src/r0/state/get_state_events_for_key.rs b/ruma-client-api/src/r0/state/get_state_events_for_key.rs index 6c631755..b3b2d2f1 100644 --- a/ruma-client-api/src/r0/state/get_state_events_for_key.rs +++ b/ruma-client-api/src/r0/state/get_state_events_for_key.rs @@ -108,7 +108,7 @@ impl ruma_api::IncomingRequest for IncomingRequest { const METADATA: ruma_api::Metadata = METADATA; - fn try_from_http_request( + fn try_from_http_request>( request: http::Request, ) -> Result { use std::convert::TryFrom; diff --git a/ruma-client-api/src/r0/state/send_state_event.rs b/ruma-client-api/src/r0/state/send_state_event.rs index 9eb7bc86..63471094 100644 --- a/ruma-client-api/src/r0/state/send_state_event.rs +++ b/ruma-client-api/src/r0/state/send_state_event.rs @@ -108,7 +108,7 @@ impl ruma_api::IncomingRequest for IncomingRequest { const METADATA: ruma_api::Metadata = METADATA; - fn try_from_http_request( + fn try_from_http_request>( request: http::Request, ) -> Result { use std::{borrow::Cow, convert::TryFrom}; @@ -136,7 +136,7 @@ impl ruma_api::IncomingRequest for IncomingRequest { let content = { let event_type = percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()?; - let body: Box = serde_json::from_reader(body.reader())?; + let body: Box = serde_json::from_slice(body.as_ref())?; AnyStateEventContent::from_parts(&event_type, body)? }; diff --git a/ruma-client-api/src/r0/uiaa.rs b/ruma-client-api/src/r0/uiaa.rs index 81d9780a..f59bab42 100644 --- a/ruma-client-api/src/r0/uiaa.rs +++ b/ruma-client-api/src/r0/uiaa.rs @@ -2,7 +2,6 @@ use std::{collections::BTreeMap, fmt}; -use bytes::Buf; use ruma_api::{ error::{IntoHttpError, ResponseDeserializationError}, EndpointError, OutgoingResponse, @@ -10,7 +9,7 @@ use ruma_api::{ use ruma_serde::Outgoing; use serde::{Deserialize, Serialize}; use serde_json::{ - from_reader as from_json_reader, to_vec as to_json_vec, value::RawValue as RawJsonValue, + from_slice as from_json_slice, to_vec as to_json_vec, value::RawValue as RawJsonValue, Value as JsonValue, }; @@ -137,11 +136,11 @@ impl From for UiaaResponse { } impl EndpointError for UiaaResponse { - fn try_from_http_response( + fn try_from_http_response>( response: http::Response, ) -> Result { if response.status() == http::StatusCode::UNAUTHORIZED { - Ok(UiaaResponse::AuthResponse(from_json_reader(response.into_body().reader())?)) + Ok(UiaaResponse::AuthResponse(from_json_slice(response.body().as_ref())?)) } else { MatrixError::try_from_http_response(response).map(From::from) } diff --git a/ruma-client/src/lib.rs b/ruma-client/src/lib.rs index abb85e01..de194313 100644 --- a/ruma-client/src/lib.rs +++ b/ruma-client/src/lib.rs @@ -373,7 +373,9 @@ impl Client { let hyper_response = client.hyper.request(http_request.map(hyper::Body::from)).await?; let (head, body) = hyper_response.into_parts(); - let full_body = hyper::body::aggregate(body).await?; + // FIXME: Use aggregate instead of to_bytes once serde_json can parse from a reader at a + // comparable speed as reading from a slice: https://github.com/serde-rs/json/issues/160 + let full_body = hyper::body::to_bytes(body).await?; let full_response = HttpResponse::from_parts(head, full_body); Ok(ruma_api::IncomingResponse::try_from_http_response(full_response)?) diff --git a/ruma-serde-macros/src/display_as_ref_str.rs b/ruma-serde-macros/src/display_as_ref_str.rs index b3180387..e521c183 100644 --- a/ruma-serde-macros/src/display_as_ref_str.rs +++ b/ruma-serde-macros/src/display_as_ref_str.rs @@ -6,7 +6,7 @@ pub fn expand_display_as_ref_str(ident: &Ident) -> syn::Result { #[automatically_derived] impl ::std::fmt::Display for #ident { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - f.write_str(>::as_ref(self)) + f.write_str(::std::convert::AsRef::<::std::primitive::str>::as_ref(self)) } } }) diff --git a/ruma-serde-macros/src/serialize_as_ref_str.rs b/ruma-serde-macros/src/serialize_as_ref_str.rs index b179ecf6..14c79e81 100644 --- a/ruma-serde-macros/src/serialize_as_ref_str.rs +++ b/ruma-serde-macros/src/serialize_as_ref_str.rs @@ -13,8 +13,7 @@ pub fn expand_serialize_as_ref_str(ident: &Ident) -> syn::Result { where S: #ruma_serde::exports::serde::ser::Serializer, { - >::as_ref(self) - .serialize(serializer) + ::std::convert::AsRef::<::std::primitive::str>::as_ref(self).serialize(serializer) } } })