1 | use crate::add_helpers::{struct_exprs, tuple_exprs}; |
2 | use crate::utils::{add_extra_ty_param_bound_op, named_to_vec, unnamed_to_vec}; |
3 | use proc_macro2::{Span, TokenStream}; |
4 | use quote::quote; |
5 | use syn::{Data, DeriveInput, Fields, Ident}; |
6 | |
7 | pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { |
8 | let trait_ident = Ident::new(trait_name, Span::call_site()); |
9 | let method_name = trait_name.to_string(); |
10 | let method_name = method_name.trim_end_matches("Assign" ); |
11 | let method_name = method_name.to_lowercase(); |
12 | let method_ident = Ident::new(&(method_name + "_assign" ), Span::call_site()); |
13 | let input_type = &input.ident; |
14 | |
15 | let generics = add_extra_ty_param_bound_op(&input.generics, &trait_ident); |
16 | let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); |
17 | |
18 | let exprs = match input.data { |
19 | Data::Struct(ref data_struct) => match data_struct.fields { |
20 | Fields::Unnamed(ref fields) => { |
21 | tuple_exprs(&unnamed_to_vec(fields), &method_ident) |
22 | } |
23 | Fields::Named(ref fields) => { |
24 | struct_exprs(&named_to_vec(fields), &method_ident) |
25 | } |
26 | _ => panic!("Unit structs cannot use derive( {})" , trait_name), |
27 | }, |
28 | |
29 | _ => panic!("Only structs can use derive( {})" , trait_name), |
30 | }; |
31 | |
32 | quote!( |
33 | impl#impl_generics ::core::ops::#trait_ident for #input_type#ty_generics #where_clause { |
34 | #[inline] |
35 | fn #method_ident(&mut self, rhs: #input_type#ty_generics) { |
36 | #(#exprs; |
37 | )* |
38 | } |
39 | } |
40 | ) |
41 | } |
42 | |