1 | use crate::utils::{add_where_clauses_for_new_ident, SingleFieldData, State}; |
2 | use proc_macro2::{Span, TokenStream}; |
3 | use quote::quote; |
4 | use syn::{parse::Result, DeriveInput, Ident}; |
5 | |
6 | /// Provides the hook to expand `#[derive(Index)]` into an implementation of `Index` |
7 | pub fn expand(input: &DeriveInput, trait_name: &'static str) -> Result<TokenStream> { |
8 | let index_type = &Ident::new("__IdxT" , Span::call_site()); |
9 | let mut state = State::with_field_ignore( |
10 | input, |
11 | trait_name, |
12 | quote!(::core::ops), |
13 | trait_name.to_lowercase(), |
14 | )?; |
15 | state.add_trait_path_type_param(quote!(#index_type)); |
16 | let SingleFieldData { |
17 | field, |
18 | field_type, |
19 | input_type, |
20 | trait_path_with_params, |
21 | casted_trait, |
22 | member, |
23 | .. |
24 | } = state.assert_single_enabled_field(); |
25 | |
26 | let type_where_clauses = quote! { |
27 | where #field_type: #trait_path_with_params |
28 | }; |
29 | |
30 | let new_generics = add_where_clauses_for_new_ident( |
31 | &input.generics, |
32 | &[field], |
33 | index_type, |
34 | type_where_clauses, |
35 | true, |
36 | ); |
37 | |
38 | let (impl_generics, _, where_clause) = new_generics.split_for_impl(); |
39 | let (_, ty_generics, _) = input.generics.split_for_impl(); |
40 | Ok(quote! { |
41 | impl#impl_generics #trait_path_with_params for #input_type#ty_generics #where_clause |
42 | { |
43 | type Output = #casted_trait::Output; |
44 | #[inline] |
45 | fn index(&self, idx: #index_type) -> &Self::Output { |
46 | #casted_trait::index(&#member, idx) |
47 | } |
48 | } |
49 | }) |
50 | } |
51 | |