confgr_derive 0.2.1

Procedural derive macro implementation for the confgr crate
Documentation
#![allow(non_snake_case)]
use crate::{get_ident_from_type, ConfigAttributes, SUFFIX};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::{Ident, Type};

pub fn generate_conversion_impl(
    name: &Ident,
    field_data: &[(&Ident, &Type, ConfigAttributes)],
) -> TokenStream {
    let BASE_PARAMETER: Ident = format_ident!("{}", "base");
    let LAYER_PARAMETER: Ident = format_ident!("{}", "layer");

    let layer_name = format_ident!("{}{}", name, SUFFIX);

    let from_layer_conversions = field_data.iter().map(|(field_name, ty, attr)| {
        if attr.nest {
            let nested_type = get_ident_from_type(ty);
            let nested_layer_name = format_ident!("{}{}", nested_type, SUFFIX);
            quote! {
                #field_name: <#nested_type as ::core::convert::From<#nested_layer_name>>::from(#LAYER_PARAMETER.#field_name),
            }
        } else {
            quote! {
                #field_name: #LAYER_PARAMETER.#field_name.unwrap_or_else(|| #name::default().#field_name),
            }
        }
    });

    let from_base_conversions = field_data.iter().map(|(field_name, ty, attr)| {
        if attr.nest {
            let nested_type = get_ident_from_type(ty);
            let nested_layer_name = format_ident!("{}{}", nested_type, SUFFIX);
            quote! {
                #field_name: <#nested_layer_name as ::core::convert::From<#nested_type>>::from(#BASE_PARAMETER.#field_name),
            }
        } else {
            quote! {
                #field_name: Some(#BASE_PARAMETER.#field_name),
            }
        }
    });

    quote! {
        #[automatically_derived]
        impl ::core::convert::From<#layer_name> for #name {
            fn from(#LAYER_PARAMETER: #layer_name) -> Self {
                Self {
                    #( #from_layer_conversions )*
                }
            }
        }

        #[automatically_derived]
        impl ::core::convert::From<#name> for #layer_name {
            fn from(#BASE_PARAMETER: #name) -> Self {
                Self {
                    #( #from_base_conversions )*
                }
            }
        }


    }
}