use proc_macro::TokenStream;
use quote::quote;
use syn::{Data, DeriveInput, Fields, parse_macro_input};
#[cfg_attr(test, mutants::skip)]
pub fn derive_personal_data_impl(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
let mut debug_fields = quote! {};
let mut encrypted_fields = Vec::new();
let mut has_encrypted_data = false;
if let Data::Struct(data_struct) = input.data
&& let Fields::Named(fields_named) = data_struct.fields
{
for field in fields_named.named {
let field_name = field.ident.unwrap();
let has_privacy = field
.attrs
.iter()
.any(|attr| attr.path().is_ident("privacy"));
if has_privacy {
has_encrypted_data = true;
encrypted_fields.push(field_name.to_string());
debug_fields = quote! {
#debug_fields
.field(stringify!(#field_name), &"[REDACTED_BY_RULLST_SHIELD]")
};
} else {
debug_fields = quote! {
#debug_fields
.field(stringify!(#field_name), &self.#field_name)
};
}
}
}
let encrypted_fields_tokens = encrypted_fields.iter().map(|f| quote! { #f });
let expanded = quote! {
impl std::fmt::Debug for #name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(stringify!(#name))
#debug_fields
.finish()
}
}
impl rullst_orm::privacy::ComplianceModel for #name {
fn compliance_schema() -> rullst_orm::privacy::PrivacyReport {
rullst_orm::privacy::PrivacyReport {
table_name: stringify!(#name).to_lowercase(),
has_encrypted_data: #has_encrypted_data,
encrypted_fields: vec![ #( #encrypted_fields_tokens ),* ],
}
}
}
};
TokenStream::from(expanded)
}