pulsync-derive 0.1.0

ProcMacros used by Pulsync
Documentation
use proc_macro::{Span, TokenStream};
use quote::quote;
use syn::DeriveInput;

use crate::VariadicStringParams;

pub(crate) fn impl_salt_derive(ast: &DeriveInput) -> TokenStream {
    let name = &ast.ident;
    let generics = &ast.generics;
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
    let salt = ast.attrs.iter().find_map(|attr| {
        if attr.path().is_ident("salt") {
            attr.parse_args::<VariadicStringParams>().ok()
        } else {
            None
        }
    });

    match salt {
        Some(salt) => {
            let salt_format = salt;
            let mut format_str = salt_format.format_str.clone();
            let mut format_args = Vec::new();
            for field_name in &salt_format.field_names {
                let pattern = format!("{{self.{}}}", field_name);
                format_str = format_str.replace(&pattern, "{}");
                let field_ident = syn::Ident::new(field_name, Span::call_site().into());
                format_args.push(quote! { &*self.#field_ident.read().unwrap() });
            }
            let format_str_lit = syn::LitStr::new(&format_str, Span::call_site().into());
            quote! {
                impl #impl_generics Salt for #name #ty_generics #where_clause {
                    fn salt(&self) -> String {
                        format!(#format_str_lit, #(#format_args),*)
                    }
                }
            }
        }
        None => {
            quote! {
                impl #impl_generics Salt for #name #ty_generics #where_clause {}
            }
        }
    }
    .into()
}