Rewrite Api's ToTokens impl to avoid calls to append_all with string literals.
This commit is contained in:
		
							parent
							
								
									5bc253b324
								
							
						
					
					
						commit
						7b1e22eea4
					
				| @ -24,6 +24,7 @@ features = ["nightly"] | |||||||
| 
 | 
 | ||||||
| [dev-dependencies] | [dev-dependencies] | ||||||
| futures = "0.1.21" | futures = "0.1.21" | ||||||
|  | http = "0.1.5" | ||||||
| serde = "1.0.45" | serde = "1.0.45" | ||||||
| serde_derive = "1.0.45" | serde_derive = "1.0.45" | ||||||
| serde_json = "1.0.17" | serde_json = "1.0.17" | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| use quote::{ToTokens, Tokens}; | use quote::{ToTokens, Tokens}; | ||||||
| use syn::punctuated::Punctuated; | use syn::punctuated::Punctuated; | ||||||
| use syn::synom::Synom; | use syn::synom::Synom; | ||||||
| use syn::{Field, FieldValue, Meta}; | use syn::{Field, FieldValue, Ident, Meta}; | ||||||
| 
 | 
 | ||||||
| mod metadata; | mod metadata; | ||||||
| mod request; | mod request; | ||||||
| @ -52,22 +52,16 @@ impl From<RawApi> for Api { | |||||||
| impl ToTokens for Api { | impl ToTokens for Api { | ||||||
|     fn to_tokens(&self, tokens: &mut Tokens) { |     fn to_tokens(&self, tokens: &mut Tokens) { | ||||||
|         let description = &self.metadata.description; |         let description = &self.metadata.description; | ||||||
|         let method = &self.metadata.method; |         let method = Ident::from(self.metadata.method.as_ref()); | ||||||
|         let name = &self.metadata.name; |         let name = &self.metadata.name; | ||||||
|         let path = &self.metadata.path; |         let path = &self.metadata.path; | ||||||
|         let rate_limited = &self.metadata.rate_limited; |         let rate_limited = &self.metadata.rate_limited; | ||||||
|         let requires_authentication = &self.metadata.requires_authentication; |         let requires_authentication = &self.metadata.requires_authentication; | ||||||
| 
 | 
 | ||||||
|         let request_types = { |         let request = &self.request; | ||||||
|             let mut tokens = Tokens::new(); |         let request_types = quote! { #request }; | ||||||
|             self.request.to_tokens(&mut tokens); |         let response = &self.response; | ||||||
|             tokens |         let response_types = quote! { #response }; | ||||||
|         }; |  | ||||||
|         let response_types = { |  | ||||||
|             let mut tokens = Tokens::new(); |  | ||||||
|             self.response.to_tokens(&mut tokens); |  | ||||||
|             tokens |  | ||||||
|         }; |  | ||||||
| 
 | 
 | ||||||
|         let set_request_path = if self.request.has_path_fields() { |         let set_request_path = if self.request.has_path_fields() { | ||||||
|             let path_str = path.as_str(); |             let path_str = path.as_str(); | ||||||
| @ -98,9 +92,10 @@ impl ToTokens for Api { | |||||||
| 
 | 
 | ||||||
|                 if segment.starts_with(':') { |                 if segment.starts_with(':') { | ||||||
|                     let path_var = &segment[1..]; |                     let path_var = &segment[1..]; | ||||||
|  |                     let path_var_ident = Ident::from(path_var); | ||||||
| 
 | 
 | ||||||
|                     tokens.append_all(quote! { |                     tokens.append_all(quote! { | ||||||
|                         (&request_path.#path_var.to_string()); |                         (&request_path.#path_var_ident.to_string()); | ||||||
|                     }); |                     }); | ||||||
|                 } else { |                 } else { | ||||||
|                     tokens.append_all(quote! { |                     tokens.append_all(quote! { | ||||||
| @ -136,7 +131,7 @@ impl ToTokens for Api { | |||||||
|             quote! { |             quote! { | ||||||
|                 let request_body = RequestBody(request.#field_name); |                 let request_body = RequestBody(request.#field_name); | ||||||
| 
 | 
 | ||||||
|                 hyper_request.set_body(::serde_json::to_vec(&request_body)?); |                 http_request.set_body(::serde_json::to_vec(&request_body)?); | ||||||
|             } |             } | ||||||
|         } else if self.request.has_body_fields() { |         } else if self.request.has_body_fields() { | ||||||
|             let request_body_init_fields = self.request.request_body_init_fields(); |             let request_body_init_fields = self.request.request_body_init_fields(); | ||||||
| @ -146,7 +141,7 @@ impl ToTokens for Api { | |||||||
|                     #request_body_init_fields |                     #request_body_init_fields | ||||||
|                 }; |                 }; | ||||||
| 
 | 
 | ||||||
|                 hyper_request.set_body(::serde_json::to_vec(&request_body)?); |                 http_request.set_body(::serde_json::to_vec(&request_body)?); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             Tokens::new() |             Tokens::new() | ||||||
| @ -155,10 +150,8 @@ impl ToTokens for Api { | |||||||
|         let deserialize_response_body = if let Some(field) = self.response.newtype_body_field() { |         let deserialize_response_body = if let Some(field) = self.response.newtype_body_field() { | ||||||
|             let field_type = &field.ty; |             let field_type = &field.ty; | ||||||
| 
 | 
 | ||||||
|             let mut tokens = Tokens::new(); |             quote! { | ||||||
| 
 |                 let future_response = http_response.body() | ||||||
|             tokens.append_all(quote! { |  | ||||||
|                 let future_response = hyper_response.body() |  | ||||||
|                     .fold::<_, _, Result<_, ::std::io::Error>>(Vec::new(), |mut bytes, chunk| { |                     .fold::<_, _, Result<_, ::std::io::Error>>(Vec::new(), |mut bytes, chunk| { | ||||||
|                         bytes.write_all(&chunk)?; |                         bytes.write_all(&chunk)?; | ||||||
| 
 | 
 | ||||||
| @ -169,16 +162,10 @@ impl ToTokens for Api { | |||||||
|                         ::serde_json::from_slice::<#field_type>(bytes.as_slice()) |                         ::serde_json::from_slice::<#field_type>(bytes.as_slice()) | ||||||
|                             .map_err(::ruma_api::Error::from) |                             .map_err(::ruma_api::Error::from) | ||||||
|                     }) |                     }) | ||||||
|             }); |             } | ||||||
| 
 |  | ||||||
|             tokens.append_all(".and_then(move |response_body| {".into_tokens()); |  | ||||||
| 
 |  | ||||||
|             tokens |  | ||||||
|         } else if self.response.has_body_fields() { |         } else if self.response.has_body_fields() { | ||||||
|             let mut tokens = Tokens::new(); |             quote! { | ||||||
| 
 |                 let future_response = http_response.body() | ||||||
|             tokens.append_all(quote! { |  | ||||||
|                 let future_response = hyper_response.body() |  | ||||||
|                     .fold::<_, _, Result<_, ::std::io::Error>>(Vec::new(), |mut bytes, chunk| { |                     .fold::<_, _, Result<_, ::std::io::Error>>(Vec::new(), |mut bytes, chunk| { | ||||||
|                         bytes.write_all(&chunk)?; |                         bytes.write_all(&chunk)?; | ||||||
| 
 | 
 | ||||||
| @ -189,29 +176,16 @@ impl ToTokens for Api { | |||||||
|                         ::serde_json::from_slice::<ResponseBody>(bytes.as_slice()) |                         ::serde_json::from_slice::<ResponseBody>(bytes.as_slice()) | ||||||
|                             .map_err(::ruma_api::Error::from) |                             .map_err(::ruma_api::Error::from) | ||||||
|                     }) |                     }) | ||||||
|             }); |             } | ||||||
| 
 |  | ||||||
|             tokens.append_all(".and_then(move |response_body| {".into_tokens()); |  | ||||||
| 
 |  | ||||||
|             tokens |  | ||||||
|         } else { |         } else { | ||||||
|             let mut tokens = Tokens::new(); |             quote! { | ||||||
| 
 |  | ||||||
|             tokens.append_all(quote! { |  | ||||||
|                 let future_response = ::futures::future::ok(()) |                 let future_response = ::futures::future::ok(()) | ||||||
|             }); |             } | ||||||
| 
 |  | ||||||
|             tokens.append_all(".and_then(move |_| {".into_tokens()); |  | ||||||
| 
 |  | ||||||
|             tokens |  | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         let mut closure_end = Tokens::new(); |  | ||||||
|         closure_end.append_all("});".into_tokens()); |  | ||||||
| 
 |  | ||||||
|         let extract_headers = if self.response.has_header_fields() { |         let extract_headers = if self.response.has_header_fields() { | ||||||
|             quote! { |             quote! { | ||||||
|                 let mut headers = hyper_response.headers().clone(); |                 let mut headers = http_response.headers().clone(); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             Tokens::new() |             Tokens::new() | ||||||
| @ -237,7 +211,7 @@ impl ToTokens for Api { | |||||||
| 
 | 
 | ||||||
|             #request_types |             #request_types | ||||||
| 
 | 
 | ||||||
|             impl ::std::convert::TryFrom<Request> for ::hyper::Request { |             impl ::std::convert::TryFrom<Request> for ::http::Request { | ||||||
|                 type Error = ::ruma_api::Error; |                 type Error = ::ruma_api::Error; | ||||||
| 
 | 
 | ||||||
|                 #[allow(unused_mut, unused_variables)] |                 #[allow(unused_mut, unused_variables)] | ||||||
| @ -245,44 +219,44 @@ impl ToTokens for Api { | |||||||
|                     let metadata = Endpoint::METADATA; |                     let metadata = Endpoint::METADATA; | ||||||
| 
 | 
 | ||||||
|                     // Use dummy homeserver url which has to be overwritten in
 |                     // Use dummy homeserver url which has to be overwritten in
 | ||||||
|                     // the calling code. Previously (with hyper::Uri) this was
 |                     // the calling code. Previously (with http::Uri) this was
 | ||||||
|                     // not required, but Url::parse only accepts absolute urls.
 |                     // not required, but Url::parse only accepts absolute urls.
 | ||||||
|                     let mut url = ::url::Url::parse("http://invalid-host-please-change/").unwrap(); |                     let mut url = ::url::Url::parse("http://invalid-host-please-change/").unwrap(); | ||||||
| 
 | 
 | ||||||
|                     { #set_request_path } |                     { #set_request_path } | ||||||
|                     { #set_request_query } |                     { #set_request_query } | ||||||
| 
 | 
 | ||||||
|                     let mut hyper_request = ::hyper::Request::new( |                     let mut http_request = ::http::Request::new( | ||||||
|                         metadata.method, |                         ::http::Method::#method, | ||||||
|                         // Every valid URL is a valid URI
 |                         // Every valid URL is a valid URI
 | ||||||
|                         url.into_string().parse().unwrap(), |                         url.into_string().parse().unwrap(), | ||||||
|                     ); |                     ); | ||||||
| 
 | 
 | ||||||
|                     { #add_body_to_request } |                     { #add_body_to_request } | ||||||
| 
 | 
 | ||||||
|                     Ok(hyper_request) |                     Ok(http_request) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             #response_types |             #response_types | ||||||
| 
 | 
 | ||||||
|             impl ::futures::future::FutureFrom<::hyper::Response> for Response { |             impl ::futures::future::FutureFrom<::http::Response> for Response { | ||||||
|                 type Future = Box<_Future<Item = Self, Error = Self::Error>>; |                 type Future = Box<_Future<Item = Self, Error = Self::Error>>; | ||||||
|                 type Error = ::ruma_api::Error; |                 type Error = ::ruma_api::Error; | ||||||
| 
 | 
 | ||||||
|                 #[allow(unused_variables)] |                 #[allow(unused_variables)] | ||||||
|                 fn future_from(hyper_response: ::hyper::Response) |                 fn future_from(http_response: ::http::Response) | ||||||
|                 -> Box<_Future<Item = Self, Error = Self::Error>> { |                 -> Box<_Future<Item = Self, Error = Self::Error>> { | ||||||
|                     #extract_headers |                     #extract_headers | ||||||
| 
 | 
 | ||||||
|                     #deserialize_response_body |                     #deserialize_response_body | ||||||
|  |                     .and_then(move |response_body| { | ||||||
|  |                         let response = Response { | ||||||
|  |                             #response_init_fields | ||||||
|  |                         }; | ||||||
| 
 | 
 | ||||||
|                     let response = Response { |                         Ok(response) | ||||||
|                         #response_init_fields |                     }); | ||||||
|                     }; |  | ||||||
| 
 |  | ||||||
|                     Ok(response) |  | ||||||
|                     #closure_end |  | ||||||
| 
 | 
 | ||||||
|                     Box::new(future_response) |                     Box::new(future_response) | ||||||
|                 } |                 } | ||||||
| @ -294,7 +268,7 @@ impl ToTokens for Api { | |||||||
| 
 | 
 | ||||||
|                 const METADATA: ::ruma_api::Metadata = ::ruma_api::Metadata { |                 const METADATA: ::ruma_api::Metadata = ::ruma_api::Metadata { | ||||||
|                     description: #description, |                     description: #description, | ||||||
|                     method: ::hyper::#method, |                     method: ::http::Method::#method, | ||||||
|                     name: #name, |                     name: #name, | ||||||
|                     path: #path, |                     path: #path, | ||||||
|                     rate_limited: #rate_limited, |                     rate_limited: #rate_limited, | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #![feature(associated_consts, proc_macro, try_from)] | #![feature(associated_consts, proc_macro, try_from)] | ||||||
| 
 | 
 | ||||||
| extern crate futures; | extern crate futures; | ||||||
|  | extern crate http; | ||||||
| extern crate ruma_api; | extern crate ruma_api; | ||||||
| extern crate ruma_api_macros; | extern crate ruma_api_macros; | ||||||
| extern crate serde; | extern crate serde; | ||||||
| @ -10,7 +11,6 @@ extern crate serde_urlencoded; | |||||||
| extern crate url; | extern crate url; | ||||||
| 
 | 
 | ||||||
| pub mod some_endpoint { | pub mod some_endpoint { | ||||||
|     use hyper::header::ContentType; |  | ||||||
|     use ruma_api_macros::ruma_api; |     use ruma_api_macros::ruma_api; | ||||||
| 
 | 
 | ||||||
|     ruma_api! { |     ruma_api! { | ||||||
| @ -28,8 +28,8 @@ pub mod some_endpoint { | |||||||
|             pub foo: String, |             pub foo: String, | ||||||
| 
 | 
 | ||||||
|             // This value will be put into the "Content-Type" HTTP header.
 |             // This value will be put into the "Content-Type" HTTP header.
 | ||||||
|             #[ruma_api(header)] |             #[ruma_api(header = "CONTENT_TYPE")] | ||||||
|             pub content_type: ContentType, |             pub content_type: String, | ||||||
| 
 | 
 | ||||||
|             // This value will be put into the query string of the request's URL.
 |             // This value will be put into the query string of the request's URL.
 | ||||||
|             #[ruma_api(query)] |             #[ruma_api(query)] | ||||||
| @ -43,8 +43,8 @@ pub mod some_endpoint { | |||||||
| 
 | 
 | ||||||
|         response { |         response { | ||||||
|             // This value will be extracted from the "Content-Type" HTTP header.
 |             // This value will be extracted from the "Content-Type" HTTP header.
 | ||||||
|             #[ruma_api(header)] |             #[ruma_api(header = "CONTENT_TYPE")] | ||||||
|             pub content_type: ContentType, |             pub content_type: String, | ||||||
| 
 | 
 | ||||||
|             // With no attribute on the field, it will be extracted from the body of the response.
 |             // With no attribute on the field, it will be extracted from the body of the response.
 | ||||||
|             pub value: String, |             pub value: String, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user