1use crate::add_assign_like;
2use crate::mul_helpers::generics_and_exprs;
3use crate::utils::{AttrParams, MultiFieldData, RefType, State};
4use proc_macro2::{Span, TokenStream};
5use quote::quote;
6use std::collections::HashSet;
7use std::iter;
8use syn::{DeriveInput, Ident, Result};
9
10pub 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