1 | use crate::utils::{ |
2 | add_extra_generic_param, add_extra_ty_param_bound_ref, SingleFieldData, State, |
3 | }; |
4 | use proc_macro2::TokenStream; |
5 | use quote::{quote, ToTokens}; |
6 | use syn::{parse::Result, DeriveInput}; |
7 | |
8 | /// Provides the hook to expand `#[derive(IntoIterator)]` into an implementation of `IntoIterator` |
9 | pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> { |
10 | let state = State::with_field_ignore_and_refs( |
11 | input, |
12 | trait_name, |
13 | quote!(::core::iter), |
14 | String::from("into_iterator" ), |
15 | )?; |
16 | let SingleFieldData { |
17 | input_type, |
18 | info, |
19 | field_type, |
20 | member, |
21 | trait_path, |
22 | .. |
23 | } = state.assert_single_enabled_field(); |
24 | |
25 | let mut tokens = TokenStream::new(); |
26 | |
27 | for ref_type in info.ref_types() { |
28 | let reference = ref_type.reference(); |
29 | let lifetime = ref_type.lifetime(); |
30 | let reference_with_lifetime = ref_type.reference_with_lifetime(); |
31 | |
32 | let generics_impl; |
33 | let generics = |
34 | add_extra_ty_param_bound_ref(&input.generics, trait_path, ref_type); |
35 | let (_, ty_generics, where_clause) = generics.split_for_impl(); |
36 | let (impl_generics, _, _) = if ref_type.is_ref() { |
37 | generics_impl = add_extra_generic_param(&generics, lifetime.clone()); |
38 | generics_impl.split_for_impl() |
39 | } else { |
40 | generics.split_for_impl() |
41 | }; |
42 | // let generics = add_extra_ty_param_bound(&input.generics, trait_path); |
43 | let casted_trait = |
44 | "e!(<#reference_with_lifetime #field_type as #trait_path>); |
45 | let into_iterator = quote! { |
46 | impl#impl_generics #trait_path for #reference_with_lifetime #input_type#ty_generics #where_clause |
47 | { |
48 | type Item = #casted_trait::Item; |
49 | type IntoIter = #casted_trait::IntoIter; |
50 | #[inline] |
51 | fn into_iter(self) -> Self::IntoIter { |
52 | #casted_trait::into_iter(#reference #member) |
53 | } |
54 | } |
55 | }; |
56 | into_iterator.to_tokens(&mut tokens); |
57 | } |
58 | Ok(tokens) |
59 | } |
60 | |