Files
adler32
aho_corasick
alloc_no_stdlib
alloc_stdlib
ansi_term
assert_matches
atty
backtrace
backtrace_sys
bincode
binjs
binjs_convert_from_json
binjs_decode
binjs_dump
binjs_encode
binjs_es6
binjs_generate_prediction_tables
binjs_generic
binjs_io
binjs_meta
binjs_shared
bitflags
brotli
brotli_decompressor
byteorder
c2_chacha
cfg_if
clap
crc32fast
derive_more
downcast_rs
either
env_logger
failure
flate2
getrandom
humantime
inflector
cases
camelcase
case
classcase
kebabcase
pascalcase
screamingsnakecase
sentencecase
snakecase
tablecase
titlecase
traincase
numbers
deordinalize
ordinalize
suffix
foreignkey
itertools
itoa
lazy_static
libc
log
lzw
memchr
miniz_oxide
nom
ppv_lite86
proc_macro2
quick_error
quote
rand
rand_chacha
rand_core
rand_pcg
range_encoding
regex
regex_syntax
rustc_demangle
ryu
serde
serde_derive
serde_json
smallvec
strsim
syn
termcolor
textwrap
thread_local
unicode_width
unicode_xid
vec_map
weedle
which
xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use crate::utils::{
    add_extra_ty_param_bound, add_extra_where_clauses, MultiFieldData, State,
};
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{DeriveInput, Ident, Result};

pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> {
    let state = State::new(
        input,
        trait_name,
        quote!(::core::iter),
        trait_name.to_lowercase(),
    )?;
    let multi_field_data = state.enabled_fields_data();
    let MultiFieldData {
        input_type,
        field_types,
        trait_path,
        method_ident,
        ..
    } = multi_field_data.clone();

    let op_trait_name = if trait_name == "Sum" { "Add" } else { "Mul" };
    let op_trait_ident = Ident::new(op_trait_name, Span::call_site());
    let op_path = quote!(::core::ops::#op_trait_ident);
    let op_method_ident =
        Ident::new(&(op_trait_name.to_lowercase()), Span::call_site());
    let type_params: Vec<_> = input
        .generics
        .type_params()
        .map(|t| t.ident.clone())
        .collect();
    let generics = if type_params.is_empty() {
        input.generics.clone()
    } else {
        let generic_type = quote!(<#(#type_params),*>);
        let generics = add_extra_ty_param_bound(&input.generics, &trait_path);
        let operator_where_clause = quote! {
            where #input_type#generic_type: #op_path<Output=#input_type#generic_type>
        };
        add_extra_where_clauses(&generics, operator_where_clause)
    };
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

    let initializers: Vec<_> = field_types
        .iter()
        .map(|field_type| quote!(#trait_path::#method_ident(::core::iter::empty::<#field_type>())))
        .collect();
    let identity = multi_field_data.initializer(&initializers);

    Ok(quote!(
        impl#impl_generics #trait_path for #input_type#ty_generics #where_clause {
            #[inline]
            fn #method_ident<I: ::core::iter::Iterator<Item = Self>>(iter: I) -> Self {
                iter.fold(#identity, #op_path::#op_method_ident)
            }
        }
    ))
}