1
1
use proc_macro:: TokenStream ;
2
2
use quote:: { format_ident, quote} ;
3
- use syn:: { DeriveInput , Ident , Type } ;
3
+ use syn:: { parse_quote , Ident , ItemStruct , Type } ;
4
4
5
5
use crate :: Result ;
6
6
7
- pub ( crate ) fn impl_joined_value ( ast : DeriveInput ) -> Result < TokenStream > {
8
- let struct_ident = ast. ident ;
9
- let ( field_ident, field_type) : ( Vec < Ident > , Vec < Type > ) = match ast. data {
10
- syn:: Data :: Struct ( data) => get_fields_map ( data. fields ) ?. into_iter ( ) . unzip ( ) ,
11
- _ => return Err ( "expected struct" . to_string ( ) ) ,
12
- } ;
13
- let map_key: Vec < String > = field_ident. iter ( ) . map ( |v| v. to_string ( ) ) . collect ( ) ;
7
+ pub ( crate ) fn impl_joined_value ( input_struct : & ItemStruct ) -> Result < TokenStream > {
8
+ let struct_ident = & input_struct. ident ;
9
+ let ( impl_generics, ty_generics, where_clause) = input_struct. generics . split_for_impl ( ) ;
10
+ let ( field_ident, field_type) : ( Vec < _ > , Vec < _ > ) =
11
+ get_fields_map ( & input_struct. fields ) ?. into_iter ( ) . unzip ( ) ;
14
12
let struct_buffer_ident = format_ident ! ( "__bevy_impulse_{}_Buffers" , struct_ident) ;
15
13
16
- let impl_buffer_map_layout =
17
- buffer_map_layout ( & struct_buffer_ident, & field_ident, & field_type, & map_key) ;
18
- let impl_joined = joined ( & struct_buffer_ident, & struct_ident, & field_ident) ;
19
-
20
- let gen = quote ! {
21
- impl :: bevy_impulse:: JoinedValue for #struct_ident {
22
- type Buffers = #struct_buffer_ident;
23
- }
24
-
14
+ let buffer_struct: ItemStruct = parse_quote ! {
25
15
#[ derive( Clone ) ]
26
16
#[ allow( non_camel_case_types) ]
27
- struct #struct_buffer_ident {
17
+ struct #struct_buffer_ident #impl_generics #where_clause {
28
18
#(
29
19
#field_ident: :: bevy_impulse:: Buffer <#field_type>,
30
20
) *
31
21
}
22
+ } ;
23
+
24
+ let impl_buffer_map_layout = impl_buffer_map_layout ( & buffer_struct, & input_struct) ?;
25
+ let impl_joined = impl_joined ( & buffer_struct, & input_struct) ?;
26
+
27
+ let gen = quote ! {
28
+ impl #impl_generics :: bevy_impulse:: JoinedValue for #struct_ident #ty_generics #where_clause {
29
+ type Buffers = #struct_buffer_ident #ty_generics;
30
+ }
31
+
32
+ #buffer_struct
32
33
33
34
#impl_buffer_map_layout
34
35
@@ -38,28 +39,38 @@ pub(crate) fn impl_joined_value(ast: DeriveInput) -> Result<TokenStream> {
38
39
Ok ( gen. into ( ) )
39
40
}
40
41
41
- fn get_fields_map ( fields : syn:: Fields ) -> Result < Vec < ( Ident , Type ) > > {
42
+ fn get_fields_map ( fields : & syn:: Fields ) -> Result < Vec < ( & Ident , & Type ) > > {
42
43
match fields {
43
44
syn:: Fields :: Named ( data) => {
44
45
let mut idents_types = Vec :: with_capacity ( data. named . len ( ) ) ;
45
- for field in data. named {
46
- let ident = field. ident . ok_or ( "expected named fields" . to_string ( ) ) ?;
47
- idents_types. push ( ( ident, field. ty ) ) ;
46
+ for field in & data. named {
47
+ let ident = field
48
+ . ident
49
+ . as_ref ( )
50
+ . ok_or ( "expected named fields" . to_string ( ) ) ?;
51
+ idents_types. push ( ( ident, & field. ty ) ) ;
48
52
}
49
53
Ok ( idents_types)
50
54
}
51
55
_ => return Err ( "expected named fields" . to_string ( ) ) ,
52
56
}
53
57
}
54
58
55
- fn buffer_map_layout (
56
- struct_ident : & Ident ,
57
- field_ident : & Vec < Ident > ,
58
- field_type : & Vec < Type > ,
59
- map_key : & Vec < String > ,
60
- ) -> proc_macro2:: TokenStream {
61
- quote ! {
62
- impl :: bevy_impulse:: BufferMapLayout for #struct_ident {
59
+ /// Params:
60
+ /// buffer_struct: The struct to implement `BufferMapLayout`.
61
+ /// item_struct: The struct which `buffer_struct` is derived from.
62
+ fn impl_buffer_map_layout (
63
+ buffer_struct : & ItemStruct ,
64
+ item_struct : & ItemStruct ,
65
+ ) -> Result < proc_macro2:: TokenStream > {
66
+ let struct_ident = & buffer_struct. ident ;
67
+ let ( impl_generics, ty_generics, where_clause) = buffer_struct. generics . split_for_impl ( ) ;
68
+ let ( field_ident, field_type) : ( Vec < _ > , Vec < _ > ) =
69
+ get_fields_map ( & item_struct. fields ) ?. into_iter ( ) . unzip ( ) ;
70
+ let map_key: Vec < String > = field_ident. iter ( ) . map ( |v| v. to_string ( ) ) . collect ( ) ;
71
+
72
+ Ok ( quote ! {
73
+ impl #impl_generics :: bevy_impulse:: BufferMapLayout for #struct_ident #ty_generics #where_clause {
63
74
fn buffer_list( & self ) -> :: smallvec:: SmallVec <[ AnyBuffer ; 8 ] > {
64
75
use smallvec:: smallvec;
65
76
smallvec![ #(
@@ -83,16 +94,25 @@ fn buffer_map_layout(
83
94
}
84
95
}
85
96
}
97
+ . into ( ) )
86
98
}
87
99
88
- fn joined (
89
- struct_ident : & Ident ,
90
- item_struct_ident : & Ident ,
91
- field_ident : & Vec < Ident > ,
92
- ) -> proc_macro2:: TokenStream {
93
- quote ! {
94
- impl :: bevy_impulse:: Joined for #struct_ident {
95
- type Item = #item_struct_ident;
100
+ /// Params:
101
+ /// joined_struct: The struct to implement `Joined`.
102
+ /// item_struct: The associated `Item` type to use for the `Joined` implementation.
103
+ fn impl_joined (
104
+ joined_struct : & ItemStruct ,
105
+ item_struct : & ItemStruct ,
106
+ ) -> Result < proc_macro2:: TokenStream > {
107
+ let struct_ident = & joined_struct. ident ;
108
+ let item_struct_ident = & item_struct. ident ;
109
+ let ( impl_generics, ty_generics, where_clause) = item_struct. generics . split_for_impl ( ) ;
110
+ let ( field_ident, _) : ( Vec < _ > , Vec < _ > ) =
111
+ get_fields_map ( & item_struct. fields ) ?. into_iter ( ) . unzip ( ) ;
112
+
113
+ Ok ( quote ! {
114
+ impl #impl_generics :: bevy_impulse:: Joined for #struct_ident #ty_generics #where_clause {
115
+ type Item = #item_struct_ident #ty_generics;
96
116
97
117
fn pull( & self , session: :: bevy_ecs:: prelude:: Entity , world: & mut :: bevy_ecs:: prelude:: World ) -> Result <Self :: Item , :: bevy_impulse:: OperationError > {
98
118
#(
@@ -104,5 +124,5 @@ fn joined(
104
124
) * } )
105
125
}
106
126
}
107
- }
127
+ } . into ( ) )
108
128
}
0 commit comments