procmeta_core/expand/
token.rs1use proc_macro2::{Span, TokenStream};
2use quote::{format_ident, quote};
3use syn::{Data, DeriveInput, Fields, LitInt};
4
5pub fn expand(input: DeriveInput) -> TokenStream {
6 let ty = input.ident;
7 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
8 let mut result_token = quote!();
9 match &input.data {
10 Data::Struct(data) => match &data.fields {
11 syn::Fields::Named(named) => {
12 let mut let_token = quote!();
13 let mut inner_token = quote!();
14 for field in named.named.iter() {
15 let field_ident = &field.ident;
16 let_token = quote! {
17 #let_token
18 let #field_ident = self.#field_ident.get_token_stream();
19 };
20 inner_token = quote! {
21 #inner_token
22 #field_ident: ##field_ident,
23 };
24 }
25 result_token = quote! {
26 #let_token
27 quote!(#ty {
28 #inner_token
29 })
30 };
31 }
32 syn::Fields::Unnamed(unamed) => {
33 let mut let_token = quote!();
34 let mut inner_token = quote!();
35 for (index, _field) in unamed.unnamed.iter().enumerate() {
36 let field_ident = format_ident!("field_{}", index);
37 let index = LitInt::new(&index.to_string(), Span::call_site());
38 let value_token = quote!(self. #index.get_token_stream());
39 let_token = quote! {
40 #let_token
41 let #field_ident = #value_token;
42 };
43 inner_token = quote! {
44 #inner_token
45 ##field_ident,
46 };
47 }
48 result_token = quote! {
49 #let_token
50 quote!(#ty (
51 #inner_token
52 ))
53 };
54 }
55 syn::Fields::Unit => {
56 result_token = quote! {
57 quote!(#ty)
58 };
59 }
60 },
61 Data::Enum(enumer) => {
62 for variant in &enumer.variants {
63 let variant_token;
64 let variant_ident = &variant.ident;
65 let mut pat = quote!();
66 match &variant.fields {
67 Fields::Named(named) => {
68 let mut let_token = quote!();
69 let mut inner_token = quote!();
70 for field in named.named.iter() {
71 let field_ident = &field.ident;
72 pat = quote! {#pat #field_ident,};
73 let_token = quote! {
74 #let_token
75 let #field_ident = #field_ident.get_token_stream();
76 };
77 inner_token = quote! {
78 #inner_token
79 #field_ident: ##field_ident,
80 };
81 }
82 pat = quote! {{#pat}};
83
84 variant_token = quote! {
85 #let_token
86 quote!(#ty :: #variant_ident {
87 #inner_token
88 })
89 };
90 }
91 Fields::Unnamed(unamed) => {
92 let mut let_token = quote!();
93 let mut inner_token = quote!();
94 for (index, _field) in unamed.unnamed.iter().enumerate() {
95 let field_ident = format_ident!("field_{}", index);
96 pat = quote! {#pat #field_ident,};
97 let value_token = quote!(#field_ident.get_token_stream());
98 let_token = quote! {
99 #let_token
100 let #field_ident = #value_token;
101 };
102 inner_token = quote! {
103 #inner_token
104 ##field_ident,
105 };
106 }
107 pat = quote! {(#pat)};
108
109 variant_token = quote! {
110 #let_token
111 quote!(#ty :: #variant_ident (
112 #inner_token
113 ))
114 };
115 }
116 Fields::Unit => {
117 pat = quote!();
118 variant_token = quote! {
119 quote!(#ty :: #variant_ident)
120 };
121 }
122 }
123 result_token = quote! {
124 #result_token
125 #ty ::#variant_ident #pat => {
126 #variant_token
127 }
128 }
129 }
130 result_token = quote! {
131 match self {
132 #result_token
133 }
134 };
135 }
136 Data::Union(_) => unimplemented!(),
137 }
138 quote! {
139 impl #impl_generics GetTokenStream for #ty #ty_generics #where_clause {
140
141 fn get_token_stream(self) -> TokenStream {
142 #result_token
143 }
144
145 fn get_self_ty() -> TokenStream {
146 quote!(#ty)
147 }
148 }
149 }
150}