summaryrefslogtreecommitdiffstats
path: root/vendor/derive_more/src/constructor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/derive_more/src/constructor.rs')
-rw-r--r--vendor/derive_more/src/constructor.rs49
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)
+}