educe/trait_handlers/eq/
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 EqHandler;
11
12impl TraitHandler for EqHandler {
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 = "PartialEq")]
21 let contains_partial_eq = traits.contains(&Trait::PartialEq);
22
23 #[cfg(not(feature = "PartialEq"))]
24 let contains_partial_eq = false;
25
26 let type_attribute = TypeAttributeBuilder {
27 enable_flag: true,
28 enable_bound: !contains_partial_eq,
29 }
30 .build_from_eq_meta(meta)?;
31
32 let mut field_types = vec![];
33
34 if !contains_partial_eq {
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 =
82 type_attribute.bound.into_where_predicates_by_generic_parameters_check_types(
83 &ast.generics.params,
84 &syn::parse2(quote!(::core::cmp::PartialEq)).unwrap(),
85 &field_types,
86 &[quote! {::core::cmp::PartialEq}],
87 );
88
89 let mut generics = ast.generics.clone();
90 let where_clause = generics.make_where_clause();
91
92 for where_predicate in bound {
93 where_clause.predicates.push(where_predicate);
94 }
95
96 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
97
98 token_stream.extend(quote! {
99 impl #impl_generics ::core::cmp::Eq for #ident #ty_generics #where_clause {
100 }
101 });
102 }
103
104 Ok(())
105 }
106}