Deserialize response body.

This commit is contained in:
Jimmy Cuadra 2017-05-13 23:03:56 -07:00
parent f48f1c1bee
commit 13c9daf21b
4 changed files with 70 additions and 1 deletions

View File

@ -19,6 +19,7 @@ features = ["full"]
version = "0.11.11" version = "0.11.11"
[dev-dependencies] [dev-dependencies]
futures = "0.1.13"
serde = "1.0.4" serde = "1.0.4"
serde_derive = "1.0.4" serde_derive = "1.0.4"
serde_json = "1.0.2" serde_json = "1.0.2"

View File

@ -49,8 +49,34 @@ impl ToTokens for Api {
Tokens::new() Tokens::new()
}; };
let deserialize_response_body = if self.response.has_body_fields() {
quote! {
let bytes = hyper_response.body().fold::<_, _, Result<_, ::hyper::Error>>(
Vec::new(),
|mut bytes, chunk| {
bytes.write_all(&chunk).expect("failed to append body chunk");
Ok(bytes)
}).wait().expect("failed to read response body chunks into byte vector");
let response_body: ResponseBody = ::serde_json::from_slice(bytes.as_slice())
.expect("failed to deserialize body");
}
} else {
Tokens::new()
};
let response_init_fields = if self.response.has_fields() {
self.response.init_fields()
} else {
Tokens::new()
};
tokens.append(quote! { tokens.append(quote! {
use std::convert::TryFrom; use std::convert::TryFrom;
use std::io::Write;
use ::futures::{Future, Stream};
/// The API endpoint. /// The API endpoint.
#[derive(Debug)] #[derive(Debug)]
@ -61,6 +87,7 @@ impl ToTokens for Api {
impl TryFrom<Request> for ::hyper::Request { impl TryFrom<Request> for ::hyper::Request {
type Error = (); type Error = ();
#[allow(unused_mut, unused_variables)]
fn try_from(request: Request) -> Result<Self, Self::Error> { fn try_from(request: Request) -> Result<Self, Self::Error> {
let mut hyper_request = ::hyper::Request::new( let mut hyper_request = ::hyper::Request::new(
::hyper::#method, ::hyper::#method,
@ -79,7 +106,13 @@ impl ToTokens for Api {
type Error = (); type Error = ();
fn try_from(hyper_response: ::hyper::Response) -> Result<Self, Self::Error> { fn try_from(hyper_response: ::hyper::Response) -> Result<Self, Self::Error> {
Ok(Response) #deserialize_response_body
let response = Response {
#response_init_fields
};
Ok(response)
} }
} }

View File

@ -10,6 +10,39 @@ impl Response {
pub fn has_body_fields(&self) -> bool { pub fn has_body_fields(&self) -> bool {
self.fields.iter().any(|field| field.is_body()) self.fields.iter().any(|field| field.is_body())
} }
pub fn has_fields(&self) -> bool {
self.fields.len() != 0
}
pub fn init_fields(&self) -> Tokens {
let mut tokens = Tokens::new();
for response_field in self.fields.iter() {
match *response_field {
ResponseField::Body(ref field) => {
let field_name = field.ident.as_ref()
.expect("expected body field to have a name");
tokens.append(quote! {
#field_name: response_body.#field_name,
});
}
ResponseField::Header(ref name, ref field) => {
let field_name = field.ident.as_ref()
.expect("expected body field to have a name");
tokens.append(quote! {
#field_name: hyper_response.headers()
.get_raw(#name)
.expect("missing expected request header: {}", #name),
});
}
}
}
tokens
}
} }
impl From<Vec<Field>> for Response { impl From<Vec<Field>> for Response {

View File

@ -1,10 +1,12 @@
#![feature(associated_consts, proc_macro, try_from)] #![feature(associated_consts, proc_macro, try_from)]
extern crate futures;
extern crate hyper; extern crate hyper;
extern crate ruma_api; extern crate ruma_api;
extern crate ruma_api_macros; extern crate ruma_api_macros;
extern crate serde; extern crate serde;
#[macro_use] extern crate serde_derive; #[macro_use] extern crate serde_derive;
extern crate serde_json;
pub mod get_supported_versions { pub mod get_supported_versions {
use ruma_api_macros::ruma_api; use ruma_api_macros::ruma_api;