1- use quote:: quote;
1+ use quote:: { quote, format_ident } ;
22use syn:: { parenthesized, Token , parse_quote, DeriveInput , Data , Generics , GenericParam , TypeParamBound , DataEnum , DataStruct , DataUnion , Type } ;
33use proc_macro2:: { TokenStream , Ident , Span } ;
44use syn:: parse:: { self , Parse , ParseStream } ;
@@ -154,16 +154,24 @@ fn handle_type<'a, T: TypeHandler<'a>>(
154154 where_clause : TokenStream ,
155155 extra_defs : & mut Vec < TokenStream >
156156) -> Result < TokenStream , syn:: Error > {
157- let mut field_info: IndexMap < Ident , TokenStream > = IndexMap :: new ( ) ;
157+ let mut field_info: IndexMap < FieldName < ' a > , TokenStream > = IndexMap :: new ( ) ;
158158 let mut field_associated_types = Vec :: new ( ) ;
159159 let mut field_defs = Vec :: new ( ) ;
160160 target. handle_fields ( |field| {
161161 let field_name = field. name ;
162162 let field_type = & field. static_type ;
163163 field_info. insert ( field_name. clone ( ) , field. static_def . clone ( ) ) ;
164- field_associated_types. push ( quote ! ( type #field_name = #field_type; ) ) ;
164+ let associated_type_name = field_name. associated_type_name ( ) ;
165+ field_associated_types. push ( quote ! ( type #associated_type_name = #field_type; ) ) ;
165166 let field_def_type = T :: field_def_type ( Some ( quote ! ( #field_type) ) ) ;
166- field_defs. push ( quote ! ( pub #field_name: #field_def_type, ) ) ;
167+ match field_name {
168+ FieldName :: Tuple { index : _ } => {
169+ field_defs. push ( quote ! ( pub #field_def_type) ) ;
170+ }
171+ FieldName :: Named { name } => {
172+ field_defs. push ( quote ! ( pub #name: #field_def_type) ) ;
173+ }
174+ }
167175 } ) ?;
168176 let field_info_struct_name = Ident :: new (
169177 & format ! ( "_FieldInfo{}" , name) ,
@@ -173,43 +181,59 @@ fn handle_type<'a, T: TypeHandler<'a>>(
173181 & format ! ( "_FieldTrait{}" , name) ,
174182 name. span ( )
175183 ) ;
176- let field_names = field_info. keys ( ) . collect :: < Vec < _ > > ( ) ;
177- extra_defs. push ( quote ! (
178- #[ allow( missing_docs) ]
179- #[ doc( hidden) ]
180- pub struct #field_info_struct_name {
181- #( #field_defs) *
184+ let associated_type_names = field_info. keys ( ) . map ( FieldName :: associated_type_name) ;
185+ let field_info_struct_def = {
186+ let fields = quote ! ( #( #field_defs) , * ) ;
187+ let fields = if target. is_tuple_style ( ) {
188+ // NOTE: I guess a tuple-struct needs a semicolon but a regular struct doesn't....
189+ quote ! ( ( #fields) ; )
190+ } else {
191+ quote ! ( { #fields } )
192+ } ;
193+ quote ! {
194+ #[ allow( missing_docs) ]
195+ #[ doc( hidden) ]
196+ pub struct #field_info_struct_name #fields
182197 }
198+ } ;
199+ extra_defs. push ( quote ! (
200+ #field_info_struct_def
183201 #[ allow( non_camel_case_types) ]
184202 #[ doc( hidden) ]
185203 trait #field_info_trait_name {
186- #( type #field_names ; ) *
204+ #( type #associated_type_names ; ) *
187205 }
188206 #[ allow( non_camel_case_types) ]
189207 impl #impl_generics #field_info_trait_name for #name #ty_generics #where_clause {
190208 #( #field_associated_types) *
191209 }
192210 ) ) ;
193211 let field_inits = field_info. iter ( )
194- . map ( |( name, def) | quote ! ( #name: #def, ) )
212+ . map ( |( name, def) | match name {
213+ FieldName :: Tuple { .. } => quote ! ( #def) ,
214+ FieldName :: Named { name } => quote ! ( #name: #def)
215+ } )
195216 . collect :: < Vec < TokenStream > > ( ) ;
217+ let field_inits = if target. is_tuple_style ( ) {
218+ quote ! ( ( #( #field_inits, ) * ) )
219+ } else {
220+ quote ! ( { #( #field_inits, ) * } )
221+ } ;
196222 extra_defs. push ( quote ! (
197223 unsafe impl #impl_generics static_reflect:: FieldReflect for #name #ty_generics #where_clause {
198224 type NamedFieldInfo = #field_info_struct_name;
199- const NAMED_FIELD_INFO : Self :: NamedFieldInfo = #field_info_struct_name {
200- #( #field_inits) *
201- } ;
225+ const NAMED_FIELD_INFO : Self :: NamedFieldInfo = #field_info_struct_name #field_inits;
202226 }
203227 ) ) ;
204- let field_names = field_info. keys ( ) . collect :: < Vec < _ > > ( ) ;
228+ let field_access = field_info. keys ( ) . map ( |name| name . access ( ) ) . collect :: < Vec < _ > > ( ) ;
205229 let field_def_type_name = T :: field_def_type ( None ) ;
206230 let type_def_type = T :: type_def_type ( ) ;
207231 let header = quote ! {
208232 use static_reflect:: { StaticReflect , FieldReflect } ;
209233 use static_reflect:: types:: TypeInfo ;
210234 use #field_def_type_name;
211235 use #type_def_type;
212- const _FIELDS: & ' static [ #field_def_type_name<' static >] = & [ #( <#name as FieldReflect >:: NAMED_FIELD_INFO . #field_names . erase( ) ) , * ] ;
236+ const _FIELDS: & ' static [ #field_def_type_name<' static >] = & [ #( <#name as FieldReflect >:: NAMED_FIELD_INFO . #field_access . erase( ) ) , * ] ;
213237 } ;
214238 let static_def = target. create_static_def ( header) ;
215239 let into_type = T :: def_into_type ( quote ! ( _DEF) ) ;
@@ -232,14 +256,41 @@ fn enum_static_type(data: &DataEnum, name: &Ident) -> Result<TokenStream, syn::E
232256 }
233257}
234258trait TypeHandler < ' a > {
259+ fn is_tuple_style ( & self ) -> bool ;
235260 fn field_def_type ( field_type : Option < TokenStream > ) -> TokenStream ;
236261 fn type_def_type ( ) -> TokenStream ;
237262 fn def_into_type ( def_ref : TokenStream ) -> TokenStream ;
238263 fn handle_fields < F : FnMut ( FieldInfo < ' a > ) > ( & mut self , handler : F ) -> syn:: Result < ( ) > ;
239264 fn create_static_def ( self , header : TokenStream ) -> TokenStream ;
240265}
266+ #[ derive( Clone , Debug , Eq , PartialEq , Hash ) ]
267+ pub enum FieldName < ' a > {
268+ Tuple {
269+ index : usize ,
270+ } ,
271+ Named {
272+ name : & ' a Ident
273+ }
274+ }
275+ impl FieldName < ' _ > {
276+ pub fn access ( & self ) -> TokenStream {
277+ match * self {
278+ FieldName :: Tuple { index } => {
279+ let idx = syn:: Index :: from ( index) ;
280+ quote ! ( #idx)
281+ } ,
282+ FieldName :: Named { name } => quote ! ( #name) ,
283+ }
284+ }
285+ pub fn associated_type_name ( & self ) -> Ident {
286+ match * self {
287+ FieldName :: Tuple { index } => format_ident ! ( "_Tuple_{}" , index) ,
288+ FieldName :: Named { name } => name. clone ( )
289+ }
290+ }
291+ }
241292struct FieldInfo < ' a > {
242- name : & ' a Ident ,
293+ name : FieldName < ' a > ,
243294 static_type : Type ,
244295 static_def : TokenStream
245296}
@@ -256,6 +307,9 @@ impl<'a> StructHandler<'a> {
256307 }
257308}
258309impl < ' a > TypeHandler < ' a > for StructHandler < ' a > {
310+ fn is_tuple_style ( & self ) -> bool {
311+ matches ! ( self . data. fields, syn:: Fields :: Unnamed ( _) )
312+ }
259313
260314 fn field_def_type ( field_type : Option < TokenStream > ) -> TokenStream {
261315 match field_type {
@@ -274,15 +328,18 @@ impl<'a> TypeHandler<'a> for StructHandler<'a> {
274328
275329 fn handle_fields < F : FnMut ( FieldInfo < ' a > ) > ( & mut self , mut handler : F ) -> syn:: Result < ( ) > {
276330 /*
277- * NOTE: Layout algorithim for repr(C) given in reference
331+ * NOTE: Layout algorithm for repr(C) given in reference
278332 * https://doc.rust-lang.org/reference/type-layout.html#reprc-structs
279333 * We have to use recursion to compute offsets :(
280334 */
281335 let mut current_offset = self . current_offset . clone ( ) ;
282336 for ( index, field) in self . data . fields . iter ( ) . enumerate ( ) {
283337 let DeriveFieldOptions { opaque_array, assume_repr } =
284338 DeriveFieldOptions :: parse_attrs ( & field. attrs ) ?;
285- let field_name = field. ident . as_ref ( ) . expect ( "Need named fields" ) ;
339+ let field_name = match field. ident {
340+ Some ( ref name) => FieldName :: Named { name } ,
341+ None => FieldName :: Tuple { index }
342+ } ;
286343 let mut field_type = field. ty . clone ( ) ;
287344 let original_type = field_type. clone ( ) ;
288345 if opaque_array {
@@ -320,8 +377,12 @@ impl<'a> TypeHandler<'a> for StructHandler<'a> {
320377 let rem = old_offset % std:: mem:: align_of:: <#original_type>( ) ;
321378 old_offset + ( if rem == 0 { 0 } else { std:: mem:: align_of:: <#original_type>( ) - rem } )
322379 } ) ;
380+ let name_field_value = match field_name {
381+ FieldName :: Tuple { .. } => quote ! ( None ) ,
382+ FieldName :: Named { name } => quote ! ( Some ( stringify!( #name) ) )
383+ } ;
323384 let static_def = quote ! ( :: static_reflect:: types:: FieldDef {
324- name: stringify! ( #field_name ) ,
385+ name: #name_field_value ,
325386 value_type: :: static_reflect:: types:: TypeId :: <#field_type>:: get( ) ,
326387 offset: #current_offset,
327388 index: #index
@@ -378,6 +439,10 @@ struct UnionTypeHandler<'a> {
378439 name : & ' a Ident
379440}
380441impl < ' a > TypeHandler < ' a > for UnionTypeHandler < ' a > {
442+ fn is_tuple_style ( & self ) -> bool {
443+ false // unions can't have tuple-fields
444+ }
445+
381446 fn field_def_type ( field_type : Option < TokenStream > ) -> TokenStream {
382447 match field_type {
383448 None => quote ! ( static_reflect:: types:: UnionFieldDef ) ,
@@ -395,7 +460,7 @@ impl<'a> TypeHandler<'a> for UnionTypeHandler<'a> {
395460
396461 fn handle_fields < F : FnMut ( FieldInfo < ' a > ) > ( & mut self , mut handler : F ) -> syn:: Result < ( ) > {
397462 /*
398- * NOTE: Layout algorithim for repr(C) given in reference
463+ * NOTE: Layout algorithm for repr(C) given in reference
399464 * https://doc.rust-lang.org/reference/type-layout.html#reprc-unions
400465 *
401466 * Unions are pretty simple since they're just glorified `mem::transmute`
@@ -420,7 +485,7 @@ impl<'a> TypeHandler<'a> for UnionTypeHandler<'a> {
420485 index: #index
421486 } ) ;
422487 handler ( FieldInfo {
423- name : field_name,
488+ name : FieldName :: Named { name : field_name } ,
424489 static_type : field_type,
425490 static_def
426491 } ) ;
0 commit comments