serde_valid_derive 0.16.0-alpha

JSON Schema based validation tool using with serde.
Documentation
use crate::serde::rename::RenameMap;
use crate::types::Field;
use crate::validate::Validator;
use proc_macro2::TokenStream;
use quote::quote;

pub fn extract_generic_custom_validator(
    field: &impl Field,
    syn::MetaList { path, nested, .. }: &syn::MetaList,
    rename_map: &RenameMap,
) -> Result<Validator, crate::Errors> {
    let field_name = field.name();
    let field_ident = field.ident();
    let field_key = field.key();
    let rename = rename_map.get(field_name).unwrap_or(&field_key);
    let errors = field.errors_variable();

    let custom_fn_name = match nested.len() {
        0 => Err(crate::Error::validate_custom_need_item(path)),
        1 => extract_custom_fn_name(&nested[0]),
        _ => Err(crate::Error::validate_custom_tail_error(nested)),
    }
    .map_err(|error| vec![error])?;

    Ok(quote!(
        if let Err(__error) = #custom_fn_name(#field_ident) {
            #errors
                .entry(#rename)
                .or_default()
                .push(__error);
        };
    ))
}

fn extract_custom_fn_name(nested_meta: &syn::NestedMeta) -> Result<TokenStream, crate::Error> {
    match nested_meta {
        syn::NestedMeta::Meta(meta) => match meta {
            syn::Meta::List(list) => {
                let fn_name = &list.path;
                Ok(quote!(#fn_name))
            }
            syn::Meta::NameValue(name_value) => {
                Err(crate::Error::meta_name_value_not_support(name_value))
            }
            syn::Meta::Path(fn_name) => Ok(quote!(#fn_name)),
        },
        syn::NestedMeta::Lit(lit) => Err(crate::Error::literal_not_support(lit)),
    }
}