use macro_tools :: { syn, quote ::quote, proc_macro2 };
#[ allow( dead_code ) ]
pub fn generate_former_trait_detector() -> proc_macro2 ::TokenStream
{
quote! {
trait __FormerDetector< T > {
const HAS_FORMER: bool = false;
}
impl< T > __FormerDetector< T > for ()
where
T: ::former ::Former,
{
const HAS_FORMER: bool = true;
}
}
}
#[ allow( dead_code ) ]
pub fn generate_former_check(field_type: &syn ::Type) -> proc_macro2 ::TokenStream
{
quote! {
< () as __FormerDetector<#field_type >> ::HAS_FORMER
}
}
#[ allow( dead_code ) ]
#[ allow( clippy ::needless_pass_by_value ) ]
pub fn generate_smart_routing(
field_type: &syn ::Type,
subform_approach: proc_macro2 ::TokenStream,
scalar_approach: proc_macro2 ::TokenStream,
) -> proc_macro2 ::TokenStream {
let former_check = generate_former_check(field_type);
quote! {
if #former_check
{
#subform_approach
} else {
#scalar_approach
}
}
}
#[ allow( dead_code ) ]
pub fn generate_former_assertion(field_type: &syn ::Type, _context: &str) -> proc_macro2 ::TokenStream
{
quote! {
const _: fn() = || {
fn assert_former_impl< T: ::former ::Former >() {}
if false
{
assert_former_impl :: < #field_type >();
}
};
}
}
#[ derive( Debug, Clone ) ]
#[ allow( dead_code ) ]
pub struct SmartRoutingConfig
{
pub prefer_subform: bool,
pub generate_fallbacks: bool,
pub custom_error_messages: bool,
}
impl Default for SmartRoutingConfig
{
fn default() -> Self
{
Self {
prefer_subform: true,
generate_fallbacks: true,
custom_error_messages: true,
}
}
}
#[ allow( dead_code ) ]
#[ allow( clippy ::needless_pass_by_value ) ]
pub fn generate_configurable_smart_routing(
field_type: &syn ::Type,
subform_approach: proc_macro2 ::TokenStream,
scalar_approach: proc_macro2 ::TokenStream,
config: &SmartRoutingConfig,
) -> proc_macro2 ::TokenStream {
let former_check = generate_former_check(field_type);
#[ allow( clippy ::if_same_then_else ) ]
let routing_logic = if config.prefer_subform
{
quote! {
if #former_check
{
#subform_approach
} else {
#scalar_approach
}
}
} else {
quote! {
if #former_check
{
#subform_approach
} else {
#scalar_approach
}
}
};
if config.generate_fallbacks
{
let detector = generate_former_trait_detector();
quote! {
#detector
#routing_logic
}
} else {
routing_logic
}
}