extern crate proc_macro;
use proc_macro::TokenStream;
use syn::{
parse_macro_input, DeriveInput, Fields, Data
};
fn get_struct_attribute_name(input: &DeriveInput) -> Vec<String> {
let mut vec_name: Vec<String> = vec![];
match &input.data {
Data::Enum(_) => {}
Data::Struct(current_struct) => match ¤t_struct.fields {
Fields::Unit => {}
Fields::Named(fields) => {
for field in fields.named.iter() {
match &field.ident {
Some(ident) => vec_name.push(String::from(format!("{}", ident))),
None => {},
}
}
}
Fields::Unnamed(_fields) => {}
},
Data::Union(_u) => {}
}
return vec_name;
}
#[proc_macro_derive(PhoenixCheckStream)]
pub fn derive_custom_static_print_fn(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let vec_name = get_struct_attribute_name(&input);
let name = input.ident;
let mut body = String::from(format!("impl PCheckStream for {} ", name));
body += &String::from("{");
body += &String::from("fn check_value(&self, field_description: &str, reference: &Self) -> Result<bool, String>{");
for attr_name in vec_name.iter() {
body += &String::from(format!("phoenix_check_stream!(&(field_description.to_owned() + &String::from(\"\\n- {}::{}\")), self.{}, &reference.{});", name, attr_name, attr_name, attr_name));
}
body += &String::from("Ok(true)");
body += &String::from("}");
body += &String::from("}");
body.parse().unwrap()
}