62 lines
2.2 KiB
Rust
62 lines
2.2 KiB
Rust
use proc_macro::TokenStream;
|
|
use quote::{quote, ToTokens};
|
|
use syn::{parse_macro_input, Data, DeriveInput, Ident};
|
|
|
|
const REPRC_ATTRIBUTE: &'static str = "assume_reprc";
|
|
|
|
#[proc_macro_derive(DeriveReprC, attributes(assume_reprc))]
|
|
pub fn reprc_builder(item: TokenStream) -> TokenStream {
|
|
let ast = parse_macro_input!(item as DeriveInput);
|
|
|
|
let struct_name = ast.ident;
|
|
let generics = ast.generics.to_token_stream();
|
|
|
|
match ast.data {
|
|
Data::Struct(data_struct) => match data_struct.fields {
|
|
syn::Fields::Named(named_fields) => {
|
|
let reprc_fields: Vec<Ident> = named_fields
|
|
.named
|
|
.iter()
|
|
.filter_map(|field| {
|
|
if field
|
|
.attrs
|
|
.iter()
|
|
.find(|attribute| {
|
|
let segments = &attribute.path().segments;
|
|
|
|
if segments.len() < 1 {
|
|
return false;
|
|
}
|
|
|
|
segments[0].ident == REPRC_ATTRIBUTE
|
|
})
|
|
.is_some()
|
|
{
|
|
None
|
|
} else {
|
|
Some(field.ident.clone())
|
|
}
|
|
})
|
|
.map(|i| i.unwrap())
|
|
.collect();
|
|
|
|
TokenStream::from(quote! {
|
|
unsafe impl #generics ReprC for #struct_name #generics {
|
|
fn is_repr_c(&self) -> bool {
|
|
true
|
|
|
|
#(
|
|
&& (&self. #reprc_fields as &dyn ReprC) .is_repr_c()
|
|
)*
|
|
}
|
|
}
|
|
})
|
|
}
|
|
syn::Fields::Unnamed(_) => todo!("Unnamed Field not supported"),
|
|
syn::Fields::Unit => todo!("Unit not supported"),
|
|
},
|
|
|
|
Data::Enum(_) => todo!("Enum not supported"),
|
|
Data::Union(_) => todo!("Union not supported"),
|
|
}
|
|
}
|