From 5bc253b3247501bcaa96b0e61803a25bc7a8306d Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sun, 13 May 2018 01:09:45 -0700 Subject: [PATCH] Rewrite request and response ToTokens to avoid calls to append_all with string literals. --- src/api/request.rs | 135 +++++++++++++++++++++++++------------------- src/api/response.rs | 64 ++++++++++++--------- 2 files changed, 113 insertions(+), 86 deletions(-) diff --git a/src/api/request.rs b/src/api/request.rs index dd1093a6..bd90860b 100644 --- a/src/api/request.rs +++ b/src/api/request.rs @@ -135,115 +135,132 @@ impl From> for Request { } impl ToTokens for Request { - fn to_tokens(&self, mut tokens: &mut Tokens) { - tokens.append_all(quote! { + fn to_tokens(&self, tokens: &mut Tokens) { + let request_struct_header = quote! { /// Data for a request to this API endpoint. #[derive(Debug)] pub struct Request - }); + }; - if self.fields.len() == 0 { - tokens.append_all(";".into_tokens()); + let request_struct_body = if self.fields.len() == 0 { + quote!(;) } else { - tokens.append_all("{".into_tokens()); - - for request_field in self.fields.iter() { + let fields = self.fields.iter().fold(Tokens::new(), |mut field_tokens, request_field| { let field = request_field.field(); let span = field.span(); - strip_serde_attrs(field).to_tokens(&mut tokens); + strip_serde_attrs(field); - tokens.append_all(quote_spanned!(span=> #field)); + field_tokens.append_all(quote_spanned!(span=> #field,)); - tokens.append_all(",".into_tokens()); + field_tokens + }); + + quote! { + { + #fields + } } + }; - tokens.append_all("}".into_tokens()); - } + let request_body_struct; if let Some(newtype_body_field) = self.newtype_body_field() { let mut field = newtype_body_field.clone(); let ty = &field.ty; let span = field.span(); - tokens.append_all(quote_spanned! {span=> + request_body_struct = quote_spanned! {span=> /// Data in the request body. #[derive(Debug, Serialize)] struct RequestBody(#ty); - }); + }; } else if self.has_body_fields() { - tokens.append_all(quote! { - /// Data in the request body. - #[derive(Debug, Serialize)] - struct RequestBody - }); - - tokens.append_all("{".into_tokens()); - - for request_field in self.fields.iter() { + let fields = self.fields.iter().fold(Tokens::new(), |mut field_tokens, request_field| { match *request_field { RequestField::Body(ref field) => { let span = field.span(); - tokens.append_all(quote_spanned!(span=> #field)); - tokens.append_all(",".into_tokens()); + field_tokens.append_all(quote_spanned!(span=> #field,)); + + field_tokens } - _ => {} + _ => field_tokens, } - } - - tokens.append_all("}".into_tokens()); - } - - if self.has_path_fields() { - tokens.append_all(quote! { - /// Data in the request path. - #[derive(Debug, Serialize)] - struct RequestPath }); - tokens.append_all("{".into_tokens()); + request_body_struct = quote! { + /// Data in the request body. + #[derive(Debug, Serialize)] + struct RequestBody { + #fields + } + }; + } else { + request_body_struct = Tokens::new(); + } - for request_field in self.fields.iter() { + let request_path_struct; + + if self.has_path_fields() { + let fields = self.fields.iter().fold(Tokens::new(), |mut field_tokens, request_field| { match *request_field { RequestField::Path(ref field) => { let span = field.span(); - tokens.append_all(quote_spanned!(span=> #field)); + field_tokens.append_all(quote_spanned!(span=> #field,)); - tokens.append_all(",".into_tokens()); + field_tokens } - _ => {} + _ => field_tokens, } - } - - tokens.append_all("}".into_tokens()); - } - - if self.has_query_fields() { - tokens.append_all(quote! { - /// Data in the request's query string. - #[derive(Debug, Serialize)] - struct RequestQuery }); - tokens.append_all("{".into_tokens()); + request_path_struct = quote! { + /// Data in the request path. + #[derive(Debug, Serialize)] + struct RequestPath { + #fields + } + }; + } else { + request_path_struct = Tokens::new(); + } - for request_field in self.fields.iter() { + let request_query_struct; + + if self.has_query_fields() { + let fields = self.fields.iter().fold(Tokens::new(), |mut field_tokens, request_field| { match *request_field { RequestField::Query(ref field) => { let span = field.span(); - tokens.append_all(quote_spanned!(span=> #field)); + field_tokens.append_all(quote_spanned!(span=> #field)); - tokens.append_all(",".into_tokens()); + field_tokens } - _ => {} + _ => field_tokens, } - } + }); - tokens.append_all("}".into_tokens()); + request_query_struct = quote! { + /// Data in the request's query string. + #[derive(Debug, Serialize)] + struct RequestQuery { + #fields + } + }; + } else { + request_query_struct = Tokens::new(); } + + tokens.append_all(quote! { + #request_struct_header + #request_struct_body + #request_body_struct + #request_path_struct + #request_query_struct + }); } } diff --git a/src/api/response.rs b/src/api/response.rs index bd6048cc..1b0105fd 100644 --- a/src/api/response.rs +++ b/src/api/response.rs @@ -145,65 +145,75 @@ impl From> for Response { impl ToTokens for Response { fn to_tokens(&self, tokens: &mut Tokens) { - tokens.append_all(quote! { + let response_struct_header = quote! { /// Data in the response from this API endpoint. #[derive(Debug)] pub struct Response - }); + }; - if self.fields.len() == 0 { - tokens.append_all(";".into_tokens()); + let response_struct_body = if self.fields.len() == 0 { + quote!(;) } else { - tokens.append_all("{".into_tokens()); - - for response_field in self.fields.iter() { + let fields = self.fields.iter().fold(Tokens::new(), |mut fields_tokens, response_field| { let field = response_field.field(); let span = field.span(); strip_serde_attrs(field); - tokens.append_all(quote_spanned!(span=> #field)); + fields_tokens.append_all(quote_spanned!(span=> #field,)); - tokens.append_all(",".into_tokens()); + fields_tokens + }); + + quote! { + { + #fields + } } + }; - tokens.append_all("}".into_tokens()); - } + let response_body_struct; if let Some(newtype_body_field) = self.newtype_body_field() { let mut field = newtype_body_field.clone(); let ty = &field.ty; let span = field.span(); - tokens.append_all(quote_spanned! {span=> + response_body_struct = quote_spanned! {span=> /// Data in the response body. #[derive(Debug, Deserialize)] struct ResponseBody(#ty); - }); + }; } else if self.has_body_fields() { - tokens.append_all(quote! { - /// Data in the response body. - #[derive(Debug, Deserialize)] - struct ResponseBody - }); - - tokens.append_all("{".into_tokens()); - - for response_field in self.fields.iter() { + let fields = self.fields.iter().fold(Tokens::new(), |mut field_tokens, response_field| { match *response_field { ResponseField::Body(ref field) => { let span = field.span(); - tokens.append_all(quote_spanned!(span=> #field)); + field_tokens.append_all(quote_spanned!(span=> #field,)); - tokens.append_all(",".into_tokens()); + field_tokens } - _ => {} + _ => field_tokens, } - } + }); - tokens.append_all("}".into_tokens()); + response_body_struct = quote! { + /// Data in the response body. + #[derive(Debug, Deserialize)] + struct ResponseBody { + #fields + } + }; + } else { + response_body_struct = Tokens::new(); } + + tokens.append_all(quote! { + #response_struct_header + #response_struct_body + #response_body_struct + }); } }