educe/trait_handlers/copy/
mod.rs1mod models;
2
3use models::{FieldAttributeBuilder, TypeAttributeBuilder};
4use quote::quote;
5use syn::{Data, DeriveInput, Meta};
6
7use super::TraitHandler;
8use crate::Trait;
9
10pub(crate) struct CopyHandler;
11
12impl TraitHandler for CopyHandler {
13 #[inline]
14 fn trait_meta_handler(
15 ast: &DeriveInput,
16 token_stream: &mut proc_macro2::TokenStream,
17 traits: &[Trait],
18 meta: &Meta,
19 ) -> syn::Result<()> {
20 #[cfg(feature = "Clone")]
21 let contains_clone = traits.contains(&Trait::Clone);
22
23 #[cfg(not(feature = "Clone"))]
24 let contains_clone = false;
25
26 let type_attribute = TypeAttributeBuilder {
27 enable_flag: true,
28 enable_bound: !contains_clone,
29 }
30 .build_from_copy_meta(meta)?;
31
32 let mut field_types = vec![];
33
34 if !contains_clone {
36 match &ast.data {
37 Data::Struct(data) => {
38 for field in data.fields.iter() {
39 field_types.push(&field.ty);
40 let _ =
41 FieldAttributeBuilder.build_from_attributes(&field.attrs, traits)?;
42 }
43 },
44 Data::Enum(data) => {
45 for variant in data.variants.iter() {
46 let _ = TypeAttributeBuilder {
47 enable_flag: false, enable_bound: false
48 }
49 .build_from_attributes(&variant.attrs, traits)?;
50
51 for field in variant.fields.iter() {
52 field_types.push(&field.ty);
53 let _ = FieldAttributeBuilder
54 .build_from_attributes(&field.attrs, traits)?;
55 }
56 }
57 },
58 Data::Union(data) => {
59 for field in data.fields.named.iter() {
60 field_types.push(&field.ty);
61 let _ =
62 FieldAttributeBuilder.build_from_attributes(&field.attrs, traits)?;
63 }
64 },
65 }
66
67 let ident = &ast.ident;
68
69 let bound =
70 type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
71 &ast.generics.params,
72 &syn::parse2(quote!(::core::marker::Copy)).unwrap(),
73 &field_types,
74 &[quote! {::core::clone::Clone}],
75 );
76
77 let mut generics = ast.generics.clone();
78 let where_clause = generics.make_where_clause();
79
80 for where_predicate in bound {
81 where_clause.predicates.push(where_predicate);
82 }
83
84 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
85
86 token_stream.extend(quote! {
87 impl #impl_generics ::core::marker::Copy for #ident #ty_generics #where_clause {
88 }
89 });
90 }
91
92 Ok(())
93 }
94}