diff options
Diffstat (limited to 'vendor/derive_more/src/constructor.rs')
-rw-r--r-- | vendor/derive_more/src/constructor.rs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/vendor/derive_more/src/constructor.rs b/vendor/derive_more/src/constructor.rs new file mode 100644 index 000000000..14d488bfd --- /dev/null +++ b/vendor/derive_more/src/constructor.rs @@ -0,0 +1,49 @@ +use crate::utils::{ + field_idents, get_field_types, named_to_vec, numbered_vars, unnamed_to_vec, +}; +use proc_macro2::TokenStream; +use quote::quote; +use syn::{Data, DeriveInput, Field, Fields, Ident}; + +/// Provides the hook to expand `#[derive(Constructor)]` into an implementation of `Constructor` +pub fn expand(input: &DeriveInput, _: &str) -> TokenStream { + let input_type = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let ((body, vars), fields) = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + let field_vec = unnamed_to_vec(fields); + (tuple_body(input_type, &field_vec), field_vec) + } + Fields::Named(ref fields) => { + let field_vec = named_to_vec(fields); + (struct_body(input_type, &field_vec), field_vec) + } + Fields::Unit => (struct_body(input_type, &[]), vec![]), + }, + _ => panic!("Only structs can derive a constructor"), + }; + let original_types = &get_field_types(&fields); + quote! { + #[allow(missing_docs)] + impl#impl_generics #input_type#ty_generics #where_clause { + #[inline] + pub fn new(#(#vars: #original_types),*) -> #input_type#ty_generics { + #body + } + } + } +} + +fn tuple_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec<Ident>) { + let vars = &numbered_vars(fields.len(), ""); + (quote!(#return_type(#(#vars),*)), vars.clone()) +} + +fn struct_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec<Ident>) { + let field_names: &Vec<Ident> = + &field_idents(fields).iter().map(|f| (**f).clone()).collect(); + let vars = field_names; + let ret_vars = field_names.clone(); + (quote!(#return_type{#(#field_names: #vars),*}), ret_vars) +} |