From f48f1c1bee1669a2b385cd2d6e3e19242223d874 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sat, 13 May 2017 22:01:09 -0700 Subject: [PATCH] Add request body to hyper requests. --- Cargo.toml | 5 ++++ src/api.rs | 31 ++++++++++++++++++++----- src/request.rs | 50 ++++++++++++++++++++++++++++++++++++++++ tests/ruma_api_macros.rs | 2 ++ 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 90c5b376..d1964b7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,11 @@ path = "../ruma-api" features = ["full"] version = "0.11.11" +[dev-dependencies] +serde = "1.0.4" +serde_derive = "1.0.4" +serde_json = "1.0.2" + [lib] doctest = false proc-macro = true diff --git a/src/api.rs b/src/api.rs index 8af8229d..382e0eec 100644 --- a/src/api.rs +++ b/src/api.rs @@ -32,6 +32,23 @@ impl ToTokens for Api { tokens }; + let add_body_to_request = if self.request.has_body_fields() { + let request_body_init_fields = self.request.request_body_init_fields(); + + quote! { + let request_body = RequestBody { + #request_body_init_fields + }; + + hyper_request.set_body( + ::serde_json::to_vec(&request_body) + .expect("failed to serialize request body to JSON") + ); + } + } else { + Tokens::new() + }; + tokens.append(quote! { use std::convert::TryFrom; @@ -45,12 +62,14 @@ impl ToTokens for Api { type Error = (); fn try_from(request: Request) -> Result { - Ok( - ::hyper::Request::new( - ::hyper::#method, - "/".parse().expect("failed to parse request URI"), - ) - ) + let mut hyper_request = ::hyper::Request::new( + ::hyper::#method, + "/".parse().expect("failed to parse request URI"), + ); + + #add_body_to_request + + Ok(hyper_request) } } diff --git a/src/request.rs b/src/request.rs index dbb45cd2..8b04786f 100644 --- a/src/request.rs +++ b/src/request.rs @@ -10,6 +10,29 @@ impl Request { pub fn has_body_fields(&self) -> bool { self.fields.iter().any(|field| field.is_body()) } + + pub fn request_body_init_fields(&self) -> Tokens { + let mut tokens = Tokens::new(); + + for request_field in self.body_fields() { + let field = match *request_field { + RequestField::Body(ref field) => field, + _ => panic!("expected body field"), + }; + + let field_name = field.ident.as_ref().expect("expected body field to have a name"); + + tokens.append(quote! { + #field_name: request.#field_name, + }); + } + + tokens + } + + fn body_fields(&self) -> RequestBodyFields { + RequestBodyFields::new(&self.fields) + } } impl From> for Request { @@ -112,3 +135,30 @@ impl RequestField { } } } + +#[derive(Debug)] +pub struct RequestBodyFields<'a> { + fields: &'a [RequestField], + index: usize, +} + +impl<'a> RequestBodyFields<'a> { + pub fn new(fields: &'a [RequestField]) -> Self { + RequestBodyFields { + fields, + index: 0, + } + } +} + +impl<'a> Iterator for RequestBodyFields<'a> { + type Item = &'a RequestField; + + fn next(&mut self) -> Option<&'a RequestField> { + let value = self.fields.get(self.index); + + self.index += 1; + + value + } +} diff --git a/tests/ruma_api_macros.rs b/tests/ruma_api_macros.rs index 05385fc9..9364d28a 100644 --- a/tests/ruma_api_macros.rs +++ b/tests/ruma_api_macros.rs @@ -3,6 +3,8 @@ extern crate hyper; extern crate ruma_api; extern crate ruma_api_macros; +extern crate serde; +#[macro_use] extern crate serde_derive; pub mod get_supported_versions { use ruma_api_macros::ruma_api;