Move new type body init field (last field initialized)

This commit is contained in:
Devin Ragotzy 2020-07-28 17:12:32 -04:00
parent 39c36176a6
commit 4c01fee5c5
2 changed files with 29 additions and 8 deletions

View File

@ -163,7 +163,7 @@ impl Request {
request_field_kind: RequestFieldKind, request_field_kind: RequestFieldKind,
src: TokenStream, src: TokenStream,
) -> TokenStream { ) -> TokenStream {
let fields = self.fields.iter().filter_map(|f| { let process_field = |f: &RequestField| {
f.field_of_kind(request_field_kind).map(|field| { f.field_of_kind(request_field_kind).map(|field| {
let field_name = let field_name =
field.ident.as_ref().expect("expected field to have an identifier"); field.ident.as_ref().expect("expected field to have an identifier");
@ -176,7 +176,20 @@ impl Request {
#field_name: #src.#field_name #field_name: #src.#field_name
} }
}) })
}); };
let mut fields = vec![];
let mut new_type_body = None;
for field in &self.fields {
if let RequestField::NewtypeRawBody(_) = field {
new_type_body = process_field(field);
} else {
fields.extend(process_field(field));
}
}
// Move field that consumes `request` to the end of the init list.
fields.extend(new_type_body);
quote! { #(#fields,)* } quote! { #(#fields,)* }
} }

View File

@ -38,14 +38,16 @@ impl Response {
/// Produces code for a response struct initializer. /// Produces code for a response struct initializer.
pub fn init_fields(&self) -> TokenStream { pub fn init_fields(&self) -> TokenStream {
let fields = self.fields.iter().map(|response_field| { let mut fields = vec![];
let mut new_type_raw_body = None;
for response_field in &self.fields {
let field = response_field.field(); let field = response_field.field();
let field_name = field.ident.as_ref().expect("expected field to have an identifier"); let field_name = field.ident.as_ref().expect("expected field to have an identifier");
let span = field.span(); let span = field.span();
let cfg_attrs = let cfg_attrs =
field.attrs.iter().filter(|a| a.path.is_ident("cfg")).collect::<Vec<_>>(); field.attrs.iter().filter(|a| a.path.is_ident("cfg")).collect::<Vec<_>>();
match response_field { fields.push(match response_field {
ResponseField::Body(_) => { ResponseField::Body(_) => {
quote_spanned! {span=> quote_spanned! {span=>
#( #cfg_attrs )* #( #cfg_attrs )*
@ -66,13 +68,19 @@ impl Response {
#field_name: response_body.0 #field_name: response_body.0
} }
} }
// This field must be instantiated last to avoid `use of move value` error.
// We are guaranteed only one new body field because of a check in `try_from`.
ResponseField::NewtypeRawBody(_) => { ResponseField::NewtypeRawBody(_) => {
quote_spanned! {span=> new_type_raw_body = Some(quote_spanned! {span=>
#field_name: response.into_body() #field_name: response.into_body()
} });
// skip adding to the vec
continue;
} }
} });
}); }
fields.extend(new_type_raw_body);
quote! { quote! {
#(#fields,)* #(#fields,)*