diff --git a/src/common/field_info.rs b/src/common/field_info.rs new file mode 100644 index 0000000..212c799 --- /dev/null +++ b/src/common/field_info.rs @@ -0,0 +1,32 @@ +use std::ops::Deref; + +use syn::Field; + +use crate::common::ident_index::IdentOrIndex; + +/// A field, in a `Fields::Named` or a `Fields::Unnamed` +/// +/// Allows unification of the data handling code, +/// to always use `{ }` syntax even for tuple data. +pub(crate) struct FieldInfo<'f> { + pub(crate) name: IdentOrIndex, + pub(crate) field: &'f Field, +} + +impl<'f> FieldInfo<'f> { + pub(crate) fn new(index: usize, field: &'f Field) -> Self { + let name = IdentOrIndex::from_ident_with_index(field.ident.as_ref(), index); + FieldInfo { + name, + field, + } + } +} + +impl<'f> Deref for FieldInfo<'f> { + type Target = &'f Field; + + fn deref(&self) -> &&'f Field { + &self.field + } +} diff --git a/src/common/ident_index.rs b/src/common/ident_index.rs index c0e38d4..496ac59 100644 --- a/src/common/ident_index.rs +++ b/src/common/ident_index.rs @@ -1,6 +1,9 @@ -use quote::ToTokens; +use std::fmt; + +use quote::{IdentFragment, ToTokens}; use syn::{Ident, Index}; +#[derive(Clone)] pub(crate) enum IdentOrIndex { Ident(Ident), Index(Index), @@ -54,3 +57,12 @@ impl IdentOrIndex { } } } + +impl IdentFragment for IdentOrIndex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Self::Ident(ident) => IdentFragment::fmt(ident, f), + Self::Index(index) => IdentFragment::fmt(index, f), + } + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs index 79e10bb..8b3ed90 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,10 +1,16 @@ #[allow(dead_code)] pub(crate) mod bound; #[allow(dead_code)] +pub(crate) mod field_info; +#[allow(dead_code)] +pub(crate) mod ident_index; +#[allow(dead_code)] pub(crate) mod path; #[allow(dead_code)] pub(crate) mod r#type; #[allow(dead_code)] +pub(crate) mod variant_info; +#[allow(dead_code)] pub(crate) mod where_predicates_bool; #[cfg(feature = "Default")] @@ -20,18 +26,6 @@ pub(crate) mod expr; ))] #[allow(dead_code)] pub(crate) mod ident_bool; -#[cfg(any( - feature = "Debug", - feature = "PartialEq", - feature = "PartialOrd", - feature = "Ord", - feature = "Hash", - feature = "Deref", - feature = "DerefMut", - feature = "Into" -))] -#[allow(dead_code)] -pub(crate) mod ident_index; #[cfg(any(feature = "PartialOrd", feature = "Ord"))] #[allow(dead_code)] pub(crate) mod int; diff --git a/src/common/variant_info.rs b/src/common/variant_info.rs new file mode 100644 index 0000000..15047f6 --- /dev/null +++ b/src/common/variant_info.rs @@ -0,0 +1,50 @@ +use std::iter; + +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; +use syn::{Data, Ident, Variant}; + +pub(crate) struct VariantInfo<'v> { + pub(crate) variant: Option<&'v Variant>, + pub(crate) fields: &'v syn::Fields, + pub(crate) attrs: &'v [syn::Attribute], +} + +pub(crate) struct VariantSelector<'v> { + pub(crate) name: Option<&'v Ident>, +} + +impl<'v> VariantInfo<'v> { + pub(crate) fn iter_from_data(data: &'v syn::Data) -> Box + 'v> { + match data { + Data::Struct(s) => Box::new(iter::once(VariantInfo { + variant: None, + fields: &s.fields, + attrs: &[], + })), + + Data::Enum(e) => Box::new(e.variants.iter().map(|v| VariantInfo { + variant: Some(v), + fields: &v.fields, + attrs: &v.attrs, + })), + + Data::Union(_) => panic!("VariantInfo cannot be used for unions"), + } + } + + pub(crate) fn selector(&self) -> VariantSelector<'v> { + let name = self.variant.as_ref().map(|v| &v.ident); + VariantSelector { + name, + } + } +} + +impl ToTokens for VariantSelector<'_> { + fn to_tokens(&self, out: &mut TokenStream) { + if let Some(name) = &self.name { + quote! { :: #name }.to_tokens(out) + } + } +} diff --git a/src/trait_handlers/clone/clone_data.rs b/src/trait_handlers/clone/clone_data.rs new file mode 100644 index 0000000..b1ff5cd --- /dev/null +++ b/src/trait_handlers/clone/clone_data.rs @@ -0,0 +1,201 @@ +use quote::{format_ident, quote}; +use syn::{DeriveInput, Meta, Type}; + +use super::models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder}; +use crate::{ + common::{field_info::FieldInfo, variant_info::VariantInfo}, + supported_traits::Trait, + TraitHandler, +}; + +pub(crate) struct CloneDataHandler; + +impl TraitHandler for CloneDataHandler { + #[inline] + 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_bound: true + } + .build_from_clone_meta(meta)?; + + let mut clone_token_stream = proc_macro2::TokenStream::new(); + let mut clone_from_token_stream = proc_macro2::TokenStream::new(); + + type Variants<'a> = Vec<(VariantInfo<'a>, Vec<(FieldInfo<'a>, FieldAttribute)>)>; + + let mut variants: Variants = Vec::new(); + + #[cfg(feature = "Copy")] + let mut has_custom_clone_method = false; + + for variant in VariantInfo::iter_from_data(&ast.data) { + let _ = TypeAttributeBuilder { + enable_flag: false, enable_bound: false + } + .build_from_attributes(variant.attrs, traits)?; + + let mut variant_fields: Vec<(FieldInfo, FieldAttribute)> = Vec::new(); + + for (index, field) in variant.fields.iter().enumerate() { + let field_attribute = FieldAttributeBuilder { + enable_method: true + } + .build_from_attributes(&field.attrs, traits)?; + + #[cfg(feature = "Copy")] + if field_attribute.method.is_some() { + has_custom_clone_method = true; + } + + variant_fields.push((FieldInfo::new(index, field), field_attribute)); + } + + variants.push((variant, variant_fields)); + } + + #[cfg(feature = "Copy")] + let contains_copy = !has_custom_clone_method && traits.contains(&Trait::Copy); + + #[cfg(not(feature = "Copy"))] + let contains_copy = false; + + if contains_copy { + clone_token_stream.extend(quote!(*self)); + } + + let mut clone_types: Vec<&Type> = Vec::new(); + + if variants.is_empty() { + if !contains_copy { + clone_token_stream.extend(quote!(unreachable!())); + clone_from_token_stream.extend(quote!(let _ = source;)); + } + } else { + let mut clone_variants_token_stream = proc_macro2::TokenStream::new(); + let mut clone_from_variants_token_stream = proc_macro2::TokenStream::new(); + + for (variant, variant_fields) in variants { + let variant_sel = variant.selector(); + + let mut pattern_src_token_stream = proc_macro2::TokenStream::new(); + let mut pattern_dst_token_stream = proc_macro2::TokenStream::new(); + let mut cl_fields_token_stream = proc_macro2::TokenStream::new(); + let mut cf_body_token_stream = proc_macro2::TokenStream::new(); + + for (field, field_attribute) in variant_fields { + let field_name_real = &field.name; + let field_name_src = format_ident!("_s_{}", field_name_real); + let field_name_dst = format_ident!("_d_{}", field_name_real); + + pattern_src_token_stream.extend(quote!(#field_name_real: #field_name_src,)); + pattern_dst_token_stream.extend(quote!(#field_name_real: #field_name_dst,)); + + if let Some(clone) = field_attribute.method.as_ref() { + cl_fields_token_stream.extend(quote! { + #field_name_real: #clone(#field_name_src), + }); + cf_body_token_stream + .extend(quote!(*#field_name_dst = #clone(#field_name_src);)); + } else { + clone_types.push(&field.ty); + + cl_fields_token_stream.extend(quote! { + #field_name_real: ::core::clone::Clone::clone(#field_name_src), + }); + cf_body_token_stream.extend( + quote!( ::core::clone::Clone::clone_from(#field_name_dst, #field_name_src); ), + ); + } + } + + clone_variants_token_stream.extend(quote! { + Self #variant_sel { #pattern_src_token_stream } => Self #variant_sel { #cl_fields_token_stream }, + }); + + clone_from_variants_token_stream.extend(quote! { + Self #variant_sel { #pattern_dst_token_stream } => { + if let Self #variant_sel { #pattern_src_token_stream } = source { + #cf_body_token_stream + } else { + *self = ::core::clone::Clone::clone(source); + } + }, + }); + } + + if !contains_copy { + clone_token_stream.extend(quote! { + match self { + #clone_variants_token_stream + } + }); + + clone_from_token_stream.extend(quote! { + match self { + #clone_from_variants_token_stream + } + }); + } + } + + let bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types( + &ast.generics.params, + &syn::parse2(if contains_copy { + quote!(::core::marker::Copy) + } else { + quote!(::core::clone::Clone) + }) + .unwrap(), + &clone_types, + &[], + ); + + let clone_from_fn_token_stream = if clone_from_token_stream.is_empty() { + None + } else { + Some(quote! { + #[inline] + fn clone_from(&mut self, source: &Self) { + #clone_from_token_stream + } + }) + }; + + let ident = &ast.ident; + + 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::clone::Clone for #ident #ty_generics #where_clause { + #[inline] + fn clone(&self) -> Self { + #clone_token_stream + } + + #clone_from_fn_token_stream + } + }); + + #[cfg(feature = "Copy")] + if traits.contains(&Trait::Copy) { + token_stream.extend(quote! { + impl #impl_generics ::core::marker::Copy for #ident #ty_generics #where_clause { + } + }); + } + + Ok(()) + } +} diff --git a/src/trait_handlers/clone/clone_enum.rs b/src/trait_handlers/clone/clone_enum.rs deleted file mode 100644 index 991243a..0000000 --- a/src/trait_handlers/clone/clone_enum.rs +++ /dev/null @@ -1,272 +0,0 @@ -use quote::{format_ident, quote}; -use syn::{punctuated::Punctuated, Data, DeriveInput, Field, Fields, Meta, Type, Variant}; - -use super::models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder}; -use crate::{ - common::where_predicates_bool::WherePredicates, supported_traits::Trait, TraitHandler, -}; - -pub(crate) struct CloneEnumHandler; - -impl TraitHandler for CloneEnumHandler { - #[inline] - 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_bound: true - } - .build_from_clone_meta(meta)?; - - let mut bound: WherePredicates = Punctuated::new(); - - let mut clone_token_stream = proc_macro2::TokenStream::new(); - let mut clone_from_token_stream = proc_macro2::TokenStream::new(); - - if let Data::Enum(data) = &ast.data { - type Variants<'a> = Vec<(&'a Variant, Vec<(&'a Field, FieldAttribute)>)>; - - let mut variants: Variants = Vec::new(); - - #[cfg(feature = "Copy")] - let mut has_custom_clone_method = false; - - for variant in data.variants.iter() { - let _ = TypeAttributeBuilder { - enable_flag: false, enable_bound: false - } - .build_from_attributes(&variant.attrs, traits)?; - - let mut variant_fields: Vec<(&Field, FieldAttribute)> = Vec::new(); - - for field in variant.fields.iter() { - let field_attribute = FieldAttributeBuilder { - enable_method: true - } - .build_from_attributes(&field.attrs, traits)?; - - #[cfg(feature = "Copy")] - if field_attribute.method.is_some() { - has_custom_clone_method = true; - } - - variant_fields.push((field, field_attribute)); - } - - variants.push((variant, variant_fields)); - } - - #[cfg(feature = "Copy")] - let contains_copy = !has_custom_clone_method && traits.contains(&Trait::Copy); - - #[cfg(not(feature = "Copy"))] - let contains_copy = false; - - if contains_copy { - clone_token_stream.extend(quote!(*self)); - } - - let mut clone_types: Vec<&Type> = Vec::new(); - - if variants.is_empty() { - if !contains_copy { - clone_token_stream.extend(quote!(unreachable!())); - clone_from_token_stream.extend(quote!(let _ = source;)); - } - } else { - let mut clone_variants_token_stream = proc_macro2::TokenStream::new(); - let mut clone_from_variants_token_stream = proc_macro2::TokenStream::new(); - - for (variant, variant_fields) in variants { - let variant_ident = &variant.ident; - - match &variant.fields { - Fields::Unit => { - clone_variants_token_stream.extend(quote! { - Self::#variant_ident => Self::#variant_ident, - }); - clone_from_variants_token_stream.extend(quote! { - Self::#variant_ident => { - if let Self::#variant_ident = source { - // same - } else { - *self = ::core::clone::Clone::clone(source); - } - }, - }); - }, - Fields::Named(_) => { - let mut pattern_src_token_stream = proc_macro2::TokenStream::new(); - let mut pattern_dst_token_stream = proc_macro2::TokenStream::new(); - let mut cl_fields_token_stream = proc_macro2::TokenStream::new(); - let mut cf_body_token_stream = proc_macro2::TokenStream::new(); - - for (field, field_attribute) in variant_fields { - let field_name_real = field.ident.as_ref().unwrap(); - let field_name_src = format_ident!("_s_{}", field_name_real); - let field_name_dst = format_ident!("_d_{}", field_name_real); - - pattern_src_token_stream - .extend(quote!(#field_name_real: #field_name_src,)); - pattern_dst_token_stream - .extend(quote!(#field_name_real: #field_name_dst,)); - - if let Some(clone) = field_attribute.method.as_ref() { - cl_fields_token_stream.extend(quote! { - #field_name_real: #clone(#field_name_src), - }); - cf_body_token_stream.extend( - quote!(*#field_name_dst = #clone(#field_name_src);), - ); - } else { - clone_types.push(&field.ty); - - cl_fields_token_stream.extend(quote! { - #field_name_real: ::core::clone::Clone::clone(#field_name_src), - }); - cf_body_token_stream.extend( - quote!( ::core::clone::Clone::clone_from(#field_name_dst, #field_name_src); ), - ); - } - } - - clone_variants_token_stream.extend(quote! { - Self::#variant_ident { #pattern_src_token_stream } => Self::#variant_ident { #cl_fields_token_stream }, - }); - - clone_from_variants_token_stream.extend(quote! { - Self::#variant_ident { #pattern_dst_token_stream } => { - if let Self::#variant_ident { #pattern_src_token_stream } = source { - #cf_body_token_stream - } else { - *self = ::core::clone::Clone::clone(source); - } - }, - }); - }, - Fields::Unnamed(_) => { - let mut pattern_token_stream = proc_macro2::TokenStream::new(); - let mut pattern2_token_stream = proc_macro2::TokenStream::new(); - let mut fields_token_stream = proc_macro2::TokenStream::new(); - let mut body_token_stream = proc_macro2::TokenStream::new(); - - for (index, (field, field_attribute)) in - variant_fields.into_iter().enumerate() - { - let field_name_src = format_ident!("_{}", index); - - pattern_token_stream.extend(quote!(#field_name_src,)); - - let field_name_dst = format_ident!("_{}", field_name_src); - - pattern2_token_stream.extend(quote!(#field_name_dst,)); - - if let Some(clone) = field_attribute.method.as_ref() { - fields_token_stream.extend(quote! (#clone(#field_name_src),)); - body_token_stream.extend( - quote!(*#field_name_src = #clone(#field_name_dst);), - ); - } else { - clone_types.push(&field.ty); - - fields_token_stream.extend( - quote! ( ::core::clone::Clone::clone(#field_name_src), ), - ); - body_token_stream.extend( - quote!( ::core::clone::Clone::clone_from(#field_name_src, #field_name_dst); ), - ); - } - } - - clone_variants_token_stream.extend(quote! { - Self::#variant_ident ( #pattern_token_stream ) => Self::#variant_ident ( #fields_token_stream ), - }); - - clone_from_variants_token_stream.extend(quote! { - Self::#variant_ident ( #pattern_token_stream ) => { - if let Self::#variant_ident ( #pattern2_token_stream ) = source { - #body_token_stream - } else { - *self = ::core::clone::Clone::clone(source); - } - }, - }); - }, - } - } - - if !contains_copy { - clone_token_stream.extend(quote! { - match self { - #clone_variants_token_stream - } - }); - - clone_from_token_stream.extend(quote! { - match self { - #clone_from_variants_token_stream - } - }); - } - } - - bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types( - &ast.generics.params, - &syn::parse2(if contains_copy { - quote!(::core::marker::Copy) - } else { - quote!(::core::clone::Clone) - }) - .unwrap(), - &clone_types, - &[], - ); - } - - let clone_from_fn_token_stream = if clone_from_token_stream.is_empty() { - None - } else { - Some(quote! { - #[inline] - fn clone_from(&mut self, source: &Self) { - #clone_from_token_stream - } - }) - }; - - let ident = &ast.ident; - - 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::clone::Clone for #ident #ty_generics #where_clause { - #[inline] - fn clone(&self) -> Self { - #clone_token_stream - } - - #clone_from_fn_token_stream - } - }); - - #[cfg(feature = "Copy")] - if traits.contains(&Trait::Copy) { - token_stream.extend(quote! { - impl #impl_generics ::core::marker::Copy for #ident #ty_generics #where_clause { - } - }); - } - - Ok(()) - } -} diff --git a/src/trait_handlers/clone/clone_struct.rs b/src/trait_handlers/clone/clone_struct.rs deleted file mode 100644 index 73aa8fa..0000000 --- a/src/trait_handlers/clone/clone_struct.rs +++ /dev/null @@ -1,195 +0,0 @@ -use quote::quote; -use syn::{punctuated::Punctuated, Data, DeriveInput, Field, Fields, Index, Meta, Type}; - -use super::models::{FieldAttribute, FieldAttributeBuilder, TypeAttributeBuilder}; -use crate::{ - common::where_predicates_bool::WherePredicates, supported_traits::Trait, TraitHandler, -}; - -pub(crate) struct CloneStructHandler; - -impl TraitHandler for CloneStructHandler { - #[inline] - 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_bound: true - } - .build_from_clone_meta(meta)?; - - let mut bound: WherePredicates = Punctuated::new(); - - let mut clone_token_stream = proc_macro2::TokenStream::new(); - let mut clone_from_token_stream = proc_macro2::TokenStream::new(); - - if let Data::Struct(data) = &ast.data { - let mut fields: Vec<(&Field, FieldAttribute)> = Vec::new(); - - #[cfg(feature = "Copy")] - let contains_copy = traits.contains(&Trait::Copy); - - #[cfg(not(feature = "Copy"))] - let contains_copy = false; - - if contains_copy { - clone_token_stream.extend(quote!(*self)); - } - - for field in data.fields.iter() { - let field_attribute = FieldAttributeBuilder { - enable_method: !contains_copy - } - .build_from_attributes(&field.attrs, traits)?; - - fields.push((field, field_attribute)); - } - - let mut clone_types: Vec<&Type> = Vec::new(); - - match &data.fields { - Fields::Unit => { - if !contains_copy { - clone_token_stream.extend(quote!(Self)); - clone_from_token_stream.extend(quote!(let _ = source;)); - } - }, - Fields::Named(_) => { - let mut fields_token_stream = proc_macro2::TokenStream::new(); - let mut clone_from_body_token_stream = proc_macro2::TokenStream::new(); - - if fields.is_empty() { - clone_from_body_token_stream.extend(quote!(let _ = source;)); - } else { - for (field, field_attribute) in fields { - let field_name = field.ident.as_ref().unwrap(); - - if let Some(clone) = field_attribute.method.as_ref() { - fields_token_stream.extend(quote! { - #field_name: #clone(&self.#field_name), - }); - - clone_from_body_token_stream.extend( - quote!(self.#field_name = #clone(&source.#field_name);), - ); - } else { - clone_types.push(&field.ty); - - fields_token_stream.extend(quote! { - #field_name: ::core::clone::Clone::clone(&self.#field_name), - }); - - clone_from_body_token_stream.extend( - quote!( ::core::clone::Clone::clone_from(&mut self.#field_name, &source.#field_name); ), - ); - } - } - } - - if !contains_copy { - clone_token_stream.extend(quote! { - Self { - #fields_token_stream - } - }); - - clone_from_token_stream.extend(clone_from_body_token_stream); - } - }, - Fields::Unnamed(_) => { - let mut fields_token_stream = proc_macro2::TokenStream::new(); - let mut clone_from_body_token_stream = proc_macro2::TokenStream::new(); - - if fields.is_empty() { - clone_from_body_token_stream.extend(quote!(let _ = source;)); - } else { - for (index, (field, field_attribute)) in fields.into_iter().enumerate() { - let field_name = Index::from(index); - - if let Some(clone) = field_attribute.method.as_ref() { - fields_token_stream.extend(quote!(#clone(&self.#field_name),)); - - clone_from_body_token_stream.extend( - quote!(self.#field_name = #clone(&source.#field_name);), - ); - } else { - clone_types.push(&field.ty); - - fields_token_stream.extend( - quote! ( ::core::clone::Clone::clone(&self.#field_name), ), - ); - - clone_from_body_token_stream.extend( - quote!( ::core::clone::Clone::clone_from(&mut self.#field_name, &source.#field_name); ), - ); - } - } - } - - if !contains_copy { - clone_token_stream.extend(quote!(Self ( #fields_token_stream ))); - clone_from_token_stream.extend(clone_from_body_token_stream); - } - }, - } - - bound = type_attribute.bound.into_where_predicates_by_generic_parameters_check_types( - &ast.generics.params, - &syn::parse2(if contains_copy { - quote!(::core::marker::Copy) - } else { - quote!(::core::clone::Clone) - }) - .unwrap(), - &clone_types, - &[], - ); - } - - let clone_from_fn_token_stream = if clone_from_token_stream.is_empty() { - None - } else { - Some(quote! { - #[inline] - fn clone_from(&mut self, source: &Self) { - #clone_from_token_stream - } - }) - }; - - let ident = &ast.ident; - - 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::clone::Clone for #ident #ty_generics #where_clause { - #[inline] - fn clone(&self) -> Self { - #clone_token_stream - } - - #clone_from_fn_token_stream - } - }); - - #[cfg(feature = "Copy")] - if traits.contains(&Trait::Copy) { - token_stream.extend(quote! { - impl #impl_generics ::core::marker::Copy for #ident #ty_generics #where_clause { - } - }); - } - - Ok(()) - } -} diff --git a/src/trait_handlers/clone/mod.rs b/src/trait_handlers/clone/mod.rs index 8c8a929..2d79252 100644 --- a/src/trait_handlers/clone/mod.rs +++ b/src/trait_handlers/clone/mod.rs @@ -1,5 +1,4 @@ -mod clone_enum; -mod clone_struct; +mod clone_data; mod clone_union; mod models; @@ -19,14 +18,8 @@ impl TraitHandler for CloneHandler { meta: &Meta, ) -> syn::Result<()> { match ast.data { - Data::Struct(_) => clone_struct::CloneStructHandler::trait_meta_handler( - ast, - token_stream, - traits, - meta, - ), - Data::Enum(_) => { - clone_enum::CloneEnumHandler::trait_meta_handler(ast, token_stream, traits, meta) + Data::Struct(_) | Data::Enum(_) => { + clone_data::CloneDataHandler::trait_meta_handler(ast, token_stream, traits, meta) }, Data::Union(_) => { clone_union::CloneUnionHandler::trait_meta_handler(ast, token_stream, traits, meta)