1use crate::add_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 mut state = State::with_attr_params(
12 input,
13 trait_name,
14 quote!(::core::ops),
15 trait_name.to_lowercase(),
16 AttrParams::struct_(vec!["forward"]),
17 )?;
18 if state.default_info.forward {
19 return Ok(add_like::expand(input, trait_name));
20 }
21
22 let scalar_ident = &Ident::new("__RhsT", Span::call_site());
23 state.add_trait_path_type_param(quote!(#scalar_ident));
24 let multi_field_data = state.enabled_fields_data();
25 let MultiFieldData {
26 input_type,
27 field_types,
28 ty_generics,
29 trait_path,
30 trait_path_with_params,
31 method_ident,
32 ..
33 } = multi_field_data.clone();
34
35 let tys = field_types.iter().collect::<HashSet<_>>();
36 let tys = tys.iter();
37 let scalar_iter = iter::repeat(scalar_ident);
38 let trait_path_iter = iter::repeat(trait_path);
39
40 let type_where_clauses = quote! {
41 where #(#tys: #trait_path_iter<#scalar_iter, Output=#tys>),*
42 };
43
44 let (generics, initializers) = generics_and_exprs(
45 multi_field_data.clone(),
46 scalar_ident,
47 type_where_clauses,
48 RefType::No,
49 );
50 let body = multi_field_data.initializer(&initializers);
51 let (impl_generics, _, where_clause) = generics.split_for_impl();
52 Ok(quote!(
53 impl#impl_generics #trait_path_with_params for #input_type#ty_generics #where_clause {
54 type Output = #input_type#ty_generics;
55 #[inline]
56 fn #method_ident(self, rhs: #scalar_ident) -> #input_type#ty_generics {
57 #body
58 }
59 }
60
61 ))
62}
63