cgp-tests 0.5.0-beta2

Context-generic programming meta crate
Documentation
use core::fmt::Display;

use cgp::extra::handler::{ComputerRef, ComputerRefComponent};
use cgp::prelude::*;

pub fn first_name_to_string<Context>(context: &Context) -> String
where
    Context: HasField<Symbol!("first_name"), Value: Display>,
{
    context.get_field(PhantomData).to_string()
}

pub fn last_name_to_string<Context>(context: &Context) -> String
where
    Context: HasField<Symbol!("last_name"), Value: Display>,
{
    context.get_field(PhantomData).to_string()
}

pub fn full_name_to_string<Context>(context: &Context) -> String
where
    Context: HasField<Symbol!("first_name"), Value: Display>
        + HasField<Symbol!("last_name"), Value: Display>,
{
    let composed = concate_outputs(first_name_to_string, last_name_to_string);
    composed(context)
}

pub fn concate_outputs<Context>(
    fn_a: impl Fn(&Context) -> String,
    fn_b: impl Fn(&Context) -> String,
) -> impl Fn(&Context) -> String {
    move |context| format!("{} {}", fn_a(context), fn_b(context))
}

#[cgp_new_provider]
impl<Context, Code, Input> ComputerRef<Context, Code, Input> for FirstNameToString
where
    Context: HasField<Symbol!("first_name"), Value: Display>,
{
    type Output = String;

    fn compute_ref(context: &Context, _code: PhantomData<Code>, _input: &Input) -> String {
        context.get_field(PhantomData).to_string()
    }
}

#[cgp_new_provider]
impl<Context, Code, Input> ComputerRef<Context, Code, Input> for LastNameToString
where
    Context: HasField<Symbol!("last_name"), Value: Display>,
{
    type Output = String;

    fn compute_ref(context: &Context, _code: PhantomData<Code>, _input: &Input) -> String {
        context.get_field(PhantomData).to_string()
    }
}

#[cgp_new_provider]
impl<Context, Code, Input, ProviderA, ProviderB> ComputerRef<Context, Code, Input>
    for ConcatOutputs<ProviderA, ProviderB>
where
    ProviderA: ComputerRef<Context, Code, Input, Output: Display>,
    ProviderB: ComputerRef<Context, Code, Input, Output: Display>,
{
    type Output = String;

    fn compute_ref(context: &Context, code: PhantomData<Code>, input: &Input) -> String {
        let output_a = ProviderA::compute_ref(context, code, input);
        let output_b = ProviderB::compute_ref(context, code, input);
        format!("{output_a} {output_b}")
    }
}

pub type FullNameToString = ConcatOutputs<FirstNameToString, LastNameToString>;