cgp-dispatch 0.4.2-alpha

Generalized handler interfaces for functional programming
Documentation
use cgp_core::prelude::*;
use cgp_handler::{
    Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent,
};

pub struct ExtractFieldAndHandle<Tag, Provider = UseContext>(pub PhantomData<(Tag, Provider)>);

#[cgp_provider]
impl<Context, Code, Input, Tag, Value, Provider, Output, Remainder> Computer<Context, Code, Input>
    for ExtractFieldAndHandle<Tag, Provider>
where
    Input: ExtractField<Tag, Value = Value, Remainder = Remainder>,
    Provider: Computer<Context, Code, Field<Tag, Value>, Output = Output>,
{
    type Output = Result<Output, Remainder>;

    fn compute(
        context: &Context,
        tag: PhantomData<Code>,
        input: Input,
    ) -> Result<Output, Remainder> {
        let value = input.extract_field(PhantomData::<Tag>)?;
        let output = Provider::compute(context, tag, value.into());
        Ok(output)
    }
}

#[cgp_provider]
impl<Context, Code, Input, Tag, Value, Provider, Output, Remainder>
    TryComputer<Context, Code, Input> for ExtractFieldAndHandle<Tag, Provider>
where
    Context: HasErrorType,
    Input: ExtractField<Tag, Value = Value, Remainder = Remainder>,
    Provider: TryComputer<Context, Code, Field<Tag, Value>, Output = Output>,
{
    type Output = Result<Output, Remainder>;

    fn try_compute(
        context: &Context,
        tag: PhantomData<Code>,
        input: Input,
    ) -> Result<Result<Output, Remainder>, Context::Error> {
        let value = input.extract_field(PhantomData::<Tag>);

        match value {
            Ok(value) => {
                let output = Provider::try_compute(context, tag, value.into())?;
                Ok(Ok(output))
            }
            Err(remainder) => Ok(Err(remainder)),
        }
    }
}

#[cgp_provider]
impl<
        Context,
        Code: Send,
        Input: Send,
        Tag: Send,
        Value: Send,
        Provider,
        Output: Send,
        Remainder: Send,
    > Handler<Context, Code, Input> for ExtractFieldAndHandle<Tag, Provider>
where
    Context: HasAsyncErrorType,
    Input: ExtractField<Tag, Value = Value, Remainder = Remainder>,
    Provider: Handler<Context, Code, Field<Tag, Value>, Output = Output>,
{
    type Output = Result<Output, Remainder>;

    async fn handle(
        context: &Context,
        tag: PhantomData<Code>,
        input: Input,
    ) -> Result<Result<Output, Remainder>, Context::Error> {
        let value = input.extract_field(PhantomData::<Tag>);

        match value {
            Ok(value) => {
                let output = Provider::handle(context, tag, value.into()).await?;
                Ok(Ok(output))
            }
            Err(remainder) => Ok(Err(remainder)),
        }
    }
}