cgp-handler 0.4.2-alpha

Generalized handler interfaces for functional programming
Documentation
use cgp_core::prelude::*;

use crate::{
    Computer, ComputerComponent, Handler, HandlerComponent, Producer, TryComputer,
    TryComputerComponent,
};

pub struct Promote<Provider>(pub PhantomData<Provider>);

pub struct TryPromote<Provider>(pub PhantomData<Provider>);

pub type Promote2<Provider> = Promote<Promote<Provider>>;

pub type Promote3<Provider> = Promote<Promote2<Provider>>;

#[cgp_provider]
impl<Context, Code, Input, Output, Provider> Handler<Context, Code, Input> for Promote<Provider>
where
    Context: HasAsyncErrorType,
    Provider: TryComputer<Context, Code, Input, Output = Output>,
    Code: Send,
    Input: Send,
    Output: Send,
{
    type Output = Output;

    async fn handle(
        context: &Context,
        tag: PhantomData<Code>,
        input: Input,
    ) -> Result<Output, Context::Error> {
        Provider::try_compute(context, tag, input)
    }
}

#[cgp_provider]
impl<Context, Code, Input, Output, Provider> Computer<Context, Code, Input> for Promote<Provider>
where
    Provider: Producer<Context, Code, Output = Output>,
{
    type Output = Output;

    fn compute(context: &Context, code: PhantomData<Code>, _input: Input) -> Self::Output {
        Provider::produce(context, code)
    }
}

#[cgp_provider]
impl<Context, Code, Input, Output, Provider> TryComputer<Context, Code, Input> for Promote<Provider>
where
    Context: HasErrorType,
    Provider: Computer<Context, Code, Input, Output = Output>,
{
    type Output = Output;

    fn try_compute(
        context: &Context,
        code: PhantomData<Code>,
        input: Input,
    ) -> Result<Self::Output, Context::Error> {
        Ok(Provider::compute(context, code, input))
    }
}

#[cgp_provider]
impl<Context, Code, Input, Output, Error, Provider> Handler<Context, Code, Input>
    for TryPromote<Provider>
where
    Context: CanRaiseAsyncError<Error>,
    Provider: Computer<Context, Code, Input, Output = Result<Output, Error>>,
    Code: Send,
    Input: Send,
    Output: Send,
    Error: Send,
{
    type Output = Output;

    async fn handle(
        context: &Context,
        tag: PhantomData<Code>,
        input: Input,
    ) -> Result<Output, Context::Error> {
        Provider::compute(context, tag, input).map_err(Context::raise_error)
    }
}

#[cgp_provider]
impl<Context, Code, Input, Output, Error, Provider> TryComputer<Context, Code, Input>
    for TryPromote<Provider>
where
    Context: CanRaiseError<Error>,
    Provider: Computer<Context, Code, Input, Output = Result<Output, Error>>,
{
    type Output = Output;

    fn try_compute(
        context: &Context,
        tag: PhantomData<Code>,
        input: Input,
    ) -> Result<Output, Context::Error> {
        Provider::compute(context, tag, input).map_err(Context::raise_error)
    }
}