utilities/src/reprc_proc_macro/src/lib.rs
2023-03-22 20:05:43 +01:00

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"),
}
}