1 | use crate::add_assign_like; |
2 | use crate::mul_helpers::generics_and_exprs; |
3 | use crate::utils::{AttrParams, MultiFieldData, RefType, State}; |
4 | use proc_macro2::{Span, TokenStream}; |
5 | use quote::quote; |
6 | use std::collections::HashSet; |
7 | use std::iter; |
8 | use syn::{DeriveInput, Ident, Result}; |
9 | |
10 | pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> { |
11 | let method_name = trait_name |
12 | .to_lowercase() |
13 | .trim_end_matches("assign" ) |
14 | .to_string() |
15 | + "_assign" ; |
16 | |
17 | let mut state = State::with_attr_params( |
18 | input, |
19 | trait_name, |
20 | quote!(::core::ops), |
21 | method_name, |
22 | AttrParams::struct_(vec!["forward" ]), |
23 | )?; |
24 | if state.default_info.forward { |
25 | return Ok(add_assign_like::expand(input, trait_name)); |
26 | } |
27 | let scalar_ident = &Ident::new("__RhsT" , Span::call_site()); |
28 | state.add_trait_path_type_param(quote!(#scalar_ident)); |
29 | let multi_field_data = state.enabled_fields_data(); |
30 | let MultiFieldData { |
31 | input_type, |
32 | field_types, |
33 | ty_generics, |
34 | trait_path, |
35 | trait_path_with_params, |
36 | method_ident, |
37 | .. |
38 | } = multi_field_data.clone(); |
39 | |
40 | let tys = field_types.iter().collect::<HashSet<_>>(); |
41 | let tys = tys.iter(); |
42 | let trait_path_iter = iter::repeat(trait_path_with_params); |
43 | |
44 | let type_where_clauses = quote! { |
45 | where #(#tys: #trait_path_iter),* |
46 | }; |
47 | |
48 | let (generics, exprs) = generics_and_exprs( |
49 | multi_field_data.clone(), |
50 | scalar_ident, |
51 | type_where_clauses, |
52 | RefType::Mut, |
53 | ); |
54 | let (impl_generics, _, where_clause) = generics.split_for_impl(); |
55 | |
56 | Ok(quote!( |
57 | impl#impl_generics #trait_path<#scalar_ident> for #input_type#ty_generics #where_clause{ |
58 | #[inline] |
59 | fn #method_ident(&mut self, rhs: #scalar_ident) { |
60 | #(#exprs; |
61 | )* |
62 | } |
63 | } |
64 | )) |
65 | } |
66 | |