extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Expr, Lit, Meta, Token};
use syn::punctuated::Punctuated;
pub fn gen_select_attribute_impl(item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as DeriveInput);
let name = &input.ident;
let fields = if let Data::Struct(data_struct) = &input.data {
let mut fields = Vec::new();
for field in &data_struct.fields {
let mut field_name = Some(field.ident.as_ref().unwrap().to_string());
let attrs = field
.attrs
.iter()
.find(|attr| attr.path().is_ident("select"));
if let Some(attr) = attrs {
let nested = attr
.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)
.map_err(|e| {
println!("Error parsing 'select' attribute");
e
})
.unwrap();
for meta in nested {
match meta {
Meta::Path(_) if meta.path().is_ident("ignore") => {
field_name = None;
break;
}
Meta::NameValue(name_value) if meta.path().is_ident("rename") => {
if let Expr::Lit(value) = &name_value.value {
if let Lit::Str(val) = &value.lit {
field_name = Some(val.value());
}
}
}
_ => {}
}
}
}
if let Some(value) = field_name {
fields.push(value);
}
}
fields
} else {
Vec::new()
};
let expanded = quote! {
impl SelectAttributeMacro for #name {
fn generate_select_clause() -> Vec<String> {
vec![#(#fields.to_string()),*]
}
}
};
TokenStream::from(expanded)
}