summaryrefslogtreecommitdiff
path: root/vendor/educe/src/trait_handlers/default/default_struct.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/educe/src/trait_handlers/default/default_struct.rs')
-rw-r--r--vendor/educe/src/trait_handlers/default/default_struct.rs149
1 files changed, 149 insertions, 0 deletions
diff --git a/vendor/educe/src/trait_handlers/default/default_struct.rs b/vendor/educe/src/trait_handlers/default/default_struct.rs
new file mode 100644
index 00000000..ea25b565
--- /dev/null
+++ b/vendor/educe/src/trait_handlers/default/default_struct.rs
@@ -0,0 +1,149 @@
+use quote::quote;
+use syn::{Data, DeriveInput, Fields, Meta, Type};
+
+use super::{
+ models::{FieldAttributeBuilder, TypeAttributeBuilder},
+ TraitHandler,
+};
+use crate::Trait;
+
+pub(crate) struct DefaultStructHandler;
+
+impl TraitHandler for DefaultStructHandler {
+ fn trait_meta_handler(
+ ast: &DeriveInput,
+ token_stream: &mut proc_macro2::TokenStream,
+ traits: &[Trait],
+ meta: &Meta,
+ ) -> syn::Result<()> {
+ let type_attribute = TypeAttributeBuilder {
+ enable_flag: true,
+ enable_new: true,
+ enable_expression: true,
+ enable_bound: true,
+ }
+ .build_from_default_meta(meta)?;
+
+ let mut default_types: Vec<&Type> = Vec::new();
+
+ let mut default_token_stream = proc_macro2::TokenStream::new();
+
+ if let Data::Struct(data) = &ast.data {
+ if let Some(expression) = type_attribute.expression {
+ for field in data.fields.iter() {
+ let _ = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: false,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+ }
+
+ default_token_stream.extend(quote!(#expression));
+ } else {
+ match &data.fields {
+ Fields::Unit => {
+ default_token_stream.extend(quote!(Self));
+ },
+ Fields::Named(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in data.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ let field_name = field.ident.as_ref().unwrap();
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote! {
+ #field_name: #expression,
+ });
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream.extend(quote! {
+ #field_name: <#ty as ::core::default::Default>::default(),
+ });
+ }
+ }
+
+ default_token_stream.extend(quote! {
+ Self {
+ #fields_token_stream
+ }
+ });
+ },
+ Fields::Unnamed(_) => {
+ let mut fields_token_stream = proc_macro2::TokenStream::new();
+
+ for field in data.fields.iter() {
+ let field_attribute = FieldAttributeBuilder {
+ enable_flag: false,
+ enable_expression: true,
+ }
+ .build_from_attributes(&field.attrs, traits, &field.ty)?;
+
+ if let Some(expression) = field_attribute.expression {
+ fields_token_stream.extend(quote!(#expression,));
+ } else {
+ let ty = &field.ty;
+
+ default_types.push(ty);
+
+ fields_token_stream
+ .extend(quote!(<#ty as ::core::default::Default>::default(),));
+ }
+ }
+
+ default_token_stream.extend(quote!(Self ( #fields_token_stream )));
+ },
+ }
+ }
+ }
+
+ let ident = &ast.ident;
+
+ let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
+ &ast.generics.params,
+ &syn::parse2(quote!(::core::default::Default)).unwrap(),
+ &default_types,
+ &[],
+ );
+
+ let mut generics = ast.generics.clone();
+ let where_clause = generics.make_where_clause();
+
+ for where_predicate in bound {
+ where_clause.predicates.push(where_predicate);
+ }
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ token_stream.extend(quote! {
+ impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
+ #[inline]
+ fn default() -> Self {
+ #default_token_stream
+ }
+ }
+ });
+
+ if type_attribute.new {
+ token_stream.extend(quote! {
+ impl #impl_generics #ident #ty_generics #where_clause {
+ /// Returns the "default value" for a type.
+ #[inline]
+ pub fn new() -> Self {
+ <Self as ::core::default::Default>::default()
+ }
+ }
+ });
+ }
+
+ Ok(())
+ }
+}