@@ -140,7 +140,9 @@ fn impl_abstract_type(ast: DeriveInput) -> Result<TokenStream> {
140
140
let ident = ast. ident ;
141
141
match ast. data {
142
142
Data :: Struct ( s) => match s. fields {
143
- Fields :: Named ( fields) => impl_abstract_struct_type ( ident, fields, repr) ,
143
+ Fields :: Named ( fields) => {
144
+ impl_abstract_structure_type ( ident, fields, repr, StructureKind :: Struct )
145
+ }
144
146
Fields :: Unnamed ( _) => Err ( s
145
147
. fields
146
148
. span ( )
@@ -150,12 +152,35 @@ fn impl_abstract_type(ast: DeriveInput) -> Result<TokenStream> {
150
152
. error ( "unit structs are unsupported; provide at least one named field" ) ) ,
151
153
} ,
152
154
Data :: Enum ( e) => impl_abstract_enum_type ( ident, e. variants , repr) ,
153
- Data :: Union ( u) => impl_abstract_union_type ( ident, u. fields , repr) ,
155
+ Data :: Union ( u) => impl_abstract_structure_type ( ident, u. fields , repr, StructureKind :: Union ) ,
154
156
}
155
157
}
156
158
157
- fn field_arguments ( name : & Ident , fields : & [ AbstractField ] ) -> Vec < TokenStream > {
158
- fields
159
+ enum StructureKind {
160
+ Struct ,
161
+ Union ,
162
+ }
163
+
164
+ fn impl_abstract_structure_type (
165
+ name : Ident ,
166
+ fields : FieldsNamed ,
167
+ repr : Repr ,
168
+ kind : StructureKind ,
169
+ ) -> Result < TokenStream > {
170
+ if !repr. c {
171
+ let msg = match kind {
172
+ StructureKind :: Struct => "struct must be `repr(C)`" ,
173
+ StructureKind :: Union => "union must be `repr(C)`" ,
174
+ } ;
175
+ return Err ( name. span ( ) . error ( msg) ) ;
176
+ }
177
+
178
+ let fields = fields
179
+ . named
180
+ . into_iter ( )
181
+ . map ( AbstractField :: from_field)
182
+ . collect :: < Result < Vec < _ > > > ( ) ?;
183
+ let args = fields
159
184
. iter ( )
160
185
. map ( |field| {
161
186
let ident = & field. ident ;
@@ -169,63 +194,27 @@ fn field_arguments(name: &Ident, fields: &[AbstractField]) -> Vec<TokenStream> {
169
194
:: binaryninja:: types:: MemberScope :: NoScope ,
170
195
}
171
196
} )
172
- . collect ( )
173
- }
174
-
175
- fn impl_abstract_struct_type ( name : Ident , fields : FieldsNamed , repr : Repr ) -> Result < TokenStream > {
176
- if !repr. c {
177
- return Err ( name. span ( ) . error ( "struct must be `repr(C)`" ) ) ;
178
- }
179
-
180
- let fields = fields
181
- . named
182
- . into_iter ( )
183
- . map ( AbstractField :: from_field)
184
- . collect :: < Result < Vec < _ > > > ( ) ?;
185
- let args = field_arguments ( & name, & fields) ;
186
- let packed = repr. packed . is_some ( ) ;
187
- let alignment = repr. align . map ( |align| quote ! { . set_alignment( #align) } ) ;
188
- Ok ( quote ! {
189
- impl :: binaryninja:: types:: AbstractType for #name {
190
- fn resolve_type( ) -> :: binaryninja:: rc:: Ref <:: binaryninja:: types:: Type > {
191
- :: binaryninja:: types:: Type :: structure(
192
- & :: binaryninja:: types:: Structure :: builder( )
193
- #( . insert( #args) ) *
194
- . set_width( :: std:: mem:: size_of:: <#name>( ) as u64 )
195
- . set_packed( #packed)
196
- #alignment
197
- . finalize( )
198
- )
199
- }
200
- }
201
- } )
202
- }
203
-
204
- fn impl_abstract_union_type ( name : Ident , fields : FieldsNamed , repr : Repr ) -> Result < TokenStream > {
205
- if !repr. c {
206
- return Err ( name. span ( ) . error ( "union must be `repr(C)`" ) ) ;
207
- }
208
-
209
- let fields = fields
210
- . named
211
- . into_iter ( )
212
- . map ( AbstractField :: from_field)
213
- . collect :: < Result < Vec < _ > > > ( ) ?;
214
- let args = field_arguments ( & name, & fields) ;
215
- let packed = repr. packed . is_some ( ) ;
216
- let alignment = repr. align . map ( |align| quote ! { . set_alignment( #align) } ) ;
197
+ . collect :: < Vec < _ > > ( ) ;
198
+ let is_packed = repr. packed . is_some ( ) ;
199
+ let set_alignment = repr. align . map ( |align| quote ! { . set_alignment( #align) } ) ;
200
+ let set_union = match kind {
201
+ StructureKind :: Struct => None ,
202
+ StructureKind :: Union => Some ( quote ! {
203
+ . set_structure_type(
204
+ :: binaryninja:: types:: StructureType :: UnionStructureType
205
+ )
206
+ } ) ,
207
+ } ;
217
208
Ok ( quote ! {
218
209
impl :: binaryninja:: types:: AbstractType for #name {
219
210
fn resolve_type( ) -> :: binaryninja:: rc:: Ref <:: binaryninja:: types:: Type > {
220
211
:: binaryninja:: types:: Type :: structure(
221
212
& :: binaryninja:: types:: Structure :: builder( )
222
213
#( . insert( #args) ) *
223
- . set_structure_type(
224
- :: binaryninja:: types:: StructureType :: UnionStructureType
225
- )
226
214
. set_width( :: std:: mem:: size_of:: <#name>( ) as u64 )
227
- . set_packed( #packed)
228
- #alignment
215
+ . set_packed( #is_packed)
216
+ #set_alignment
217
+ #set_union
229
218
. finalize( )
230
219
)
231
220
}
0 commit comments