Skip to content

Commit b40cd37

Browse files
committed
Allow named types using a #[named] field attribute
1 parent 4f7df98 commit b40cd37

File tree

1 file changed

+28
-6
lines changed
  • rust/binaryninja-derive/src

1 file changed

+28
-6
lines changed

rust/binaryninja-derive/src/lib.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt};
33
use quote::quote;
44
use syn::spanned::Spanned;
55
use syn::{
6-
parenthesized, parse_macro_input, token, Attribute, Data, DeriveInput, Fields, FieldsNamed,
7-
Ident, LitInt, Path, Variant,
6+
parenthesized, parse_macro_input, token, Attribute, Data, DeriveInput, Field, Fields,
7+
FieldsNamed, Ident, LitInt, Path, Variant,
88
};
99

1010
type Result<T> = std::result::Result<T, Diagnostic>;
@@ -23,7 +23,14 @@ impl Repr {
2323
let mut align = None;
2424
let mut primitive = None;
2525
for attr in attrs {
26-
if attr.path().is_ident("repr") {
26+
let Some(ident) = attr.path().get_ident() else {
27+
continue;
28+
};
29+
if ident == "named" {
30+
return Err(attr
31+
.span()
32+
.error("`#[named]` attribute can only be applied to fields"));
33+
} else if ident == "repr" {
2734
attr.parse_nested_meta(|meta| {
2835
if let Some(ident) = meta.path.get_ident() {
2936
if ident == "C" {
@@ -69,7 +76,7 @@ fn ident_in_list<const N: usize>(ident: &Ident, list: [&'static str; N]) -> bool
6976
list.iter().any(|id| ident == id)
7077
}
7178

72-
#[proc_macro_derive(AbstractType)]
79+
#[proc_macro_derive(AbstractType, attributes(named))]
7380
pub fn abstract_type_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
7481
let input = parse_macro_input!(input as DeriveInput);
7582
match impl_abstract_type(input) {
@@ -102,15 +109,30 @@ fn impl_abstract_type(ast: DeriveInput) -> Result<TokenStream> {
102109
}
103110
}
104111

112+
fn field_resolved_type(field: &Field) -> TokenStream {
113+
let ty = &field.ty;
114+
let resolved_ty = quote! { <#ty as ::binaryninja::types::AbstractType>::resolve_type() };
115+
if field.attrs.iter().any(|attr| attr.path().is_ident("named")) {
116+
quote! {
117+
::binaryninja::types::Type::named_type_from_type(
118+
stringify!(#ty),
119+
&#resolved_ty
120+
)
121+
}
122+
} else {
123+
resolved_ty
124+
}
125+
}
126+
105127
fn field_arguments(name: &Ident, fields: FieldsNamed) -> Vec<TokenStream> {
106128
fields
107129
.named
108130
.iter()
109131
.map(|field| {
110132
let ident = field.ident.as_ref().unwrap();
111-
let ty = &field.ty;
133+
let resolved_ty = field_resolved_type(field);
112134
quote! {
113-
&<#ty as ::binaryninja::types::AbstractType>::resolve_type(),
135+
&#resolved_ty,
114136
stringify!(#ident),
115137
::std::mem::offset_of!(#name, #ident) as u64,
116138
false,

0 commit comments

Comments
 (0)