educe/trait_handlers/default/
default_struct.rs1use quote::quote;
2use syn::{Data, DeriveInput, Fields, Meta, Type};
3
4use super::{
5 models::{FieldAttributeBuilder, TypeAttributeBuilder},
6 TraitHandler,
7};
8use crate::Trait;
9
10pub(crate) struct DefaultStructHandler;
11
12impl TraitHandler for DefaultStructHandler {
13 fn trait_meta_handler(
14 ast: &DeriveInput,
15 token_stream: &mut proc_macro2::TokenStream,
16 traits: &[Trait],
17 meta: &Meta,
18 ) -> syn::Result<()> {
19 let type_attribute = TypeAttributeBuilder {
20 enable_flag: true,
21 enable_new: true,
22 enable_expression: true,
23 enable_bound: true,
24 }
25 .build_from_default_meta(meta)?;
26
27 let mut default_types: Vec<&Type> = Vec::new();
28
29 let mut default_token_stream = proc_macro2::TokenStream::new();
30
31 if let Data::Struct(data) = &ast.data {
32 if let Some(expression) = type_attribute.expression {
33 for field in data.fields.iter() {
34 let _ = FieldAttributeBuilder {
35 enable_flag: false,
36 enable_expression: false,
37 }
38 .build_from_attributes(&field.attrs, traits, &field.ty)?;
39 }
40
41 default_token_stream.extend(quote!(#expression));
42 } else {
43 match &data.fields {
44 Fields::Unit => {
45 default_token_stream.extend(quote!(Self));
46 },
47 Fields::Named(_) => {
48 let mut fields_token_stream = proc_macro2::TokenStream::new();
49
50 for field in data.fields.iter() {
51 let field_attribute = FieldAttributeBuilder {
52 enable_flag: false,
53 enable_expression: true,
54 }
55 .build_from_attributes(&field.attrs, traits, &field.ty)?;
56
57 let field_name = field.ident.as_ref().unwrap();
58
59 if let Some(expression) = field_attribute.expression {
60 fields_token_stream.extend(quote! {
61 #field_name: #expression,
62 });
63 } else {
64 let ty = &field.ty;
65
66 default_types.push(ty);
67
68 fields_token_stream.extend(quote! {
69 #field_name: <#ty as ::core::default::Default>::default(),
70 });
71 }
72 }
73
74 default_token_stream.extend(quote! {
75 Self {
76 #fields_token_stream
77 }
78 });
79 },
80 Fields::Unnamed(_) => {
81 let mut fields_token_stream = proc_macro2::TokenStream::new();
82
83 for field in data.fields.iter() {
84 let field_attribute = FieldAttributeBuilder {
85 enable_flag: false,
86 enable_expression: true,
87 }
88 .build_from_attributes(&field.attrs, traits, &field.ty)?;
89
90 if let Some(expression) = field_attribute.expression {
91 fields_token_stream.extend(quote!(#expression,));
92 } else {
93 let ty = &field.ty;
94
95 default_types.push(ty);
96
97 fields_token_stream
98 .extend(quote!(<#ty as ::core::default::Default>::default(),));
99 }
100 }
101
102 default_token_stream.extend(quote!(Self ( #fields_token_stream )));
103 },
104 }
105 }
106 }
107
108 let ident = &ast.ident;
109
110 let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
111 &ast.generics.params,
112 &syn::parse2(quote!(::core::default::Default)).unwrap(),
113 &default_types,
114 &[],
115 );
116
117 let mut generics = ast.generics.clone();
118 let where_clause = generics.make_where_clause();
119
120 for where_predicate in bound {
121 where_clause.predicates.push(where_predicate);
122 }
123
124 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
125
126 token_stream.extend(quote! {
127 impl #impl_generics ::core::default::Default for #ident #ty_generics #where_clause {
128 #[inline]
129 fn default() -> Self {
130 #default_token_stream
131 }
132 }
133 });
134
135 if type_attribute.new {
136 token_stream.extend(quote! {
137 impl #impl_generics #ident #ty_generics #where_clause {
138 #[inline]
140 pub fn new() -> Self {
141 <Self as ::core::default::Default>::default()
142 }
143 }
144 });
145 }
146
147 Ok(())
148 }
149}