@@ -140,7 +140,9 @@ fn impl_abstract_type(ast: DeriveInput) -> Result<TokenStream> {
140140 let ident = ast. ident ;
141141 match ast. data {
142142 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+ }
144146 Fields :: Unnamed ( _) => Err ( s
145147 . fields
146148 . span ( )
@@ -150,12 +152,35 @@ fn impl_abstract_type(ast: DeriveInput) -> Result<TokenStream> {
150152 . error ( "unit structs are unsupported; provide at least one named field" ) ) ,
151153 } ,
152154 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 ) ,
154156 }
155157}
156158
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
159184 . iter ( )
160185 . map ( |field| {
161186 let ident = & field. ident ;
@@ -169,63 +194,27 @@ fn field_arguments(name: &Ident, fields: &[AbstractField]) -> Vec<TokenStream> {
169194 :: binaryninja:: types:: MemberScope :: NoScope ,
170195 }
171196 } )
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+ } ;
217208 Ok ( quote ! {
218209 impl :: binaryninja:: types:: AbstractType for #name {
219210 fn resolve_type( ) -> :: binaryninja:: rc:: Ref <:: binaryninja:: types:: Type > {
220211 :: binaryninja:: types:: Type :: structure(
221212 & :: binaryninja:: types:: Structure :: builder( )
222213 #( . insert( #args) ) *
223- . set_structure_type(
224- :: binaryninja:: types:: StructureType :: UnionStructureType
225- )
226214 . 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
229218 . finalize( )
230219 )
231220 }
0 commit comments