1use cgp_core::prelude::*;
2
3use crate::{
4 AsyncComputer, AsyncComputerComponent, Computer, ComputerComponent, Handler, HandlerComponent,
5 TryComputer, TryComputerComponent,
6};
7
8pub struct ComposeHandlers<ProviderA, ProviderB>(pub PhantomData<(ProviderA, ProviderB)>);
9
10#[cgp_provider]
11impl<Context, Code, Input, ProviderA, ProviderB> Computer<Context, Code, Input>
12 for ComposeHandlers<ProviderA, ProviderB>
13where
14 ProviderA: Computer<Context, Code, Input>,
15 ProviderB: Computer<Context, Code, ProviderA::Output>,
16{
17 type Output = ProviderB::Output;
18
19 fn compute(context: &Context, code: PhantomData<Code>, input: Input) -> Self::Output {
20 let intermediary = ProviderA::compute(context, code, input);
21 ProviderB::compute(context, code, intermediary)
22 }
23}
24
25#[cgp_provider]
26impl<Context, Code, Input, ProviderA, ProviderB> TryComputer<Context, Code, Input>
27 for ComposeHandlers<ProviderA, ProviderB>
28where
29 Context: HasErrorType,
30 ProviderA: TryComputer<Context, Code, Input>,
31 ProviderB: TryComputer<Context, Code, ProviderA::Output>,
32{
33 type Output = ProviderB::Output;
34
35 fn try_compute(
36 context: &Context,
37 code: PhantomData<Code>,
38 input: Input,
39 ) -> Result<Self::Output, Context::Error> {
40 let intermediary = ProviderA::try_compute(context, code, input)?;
41 ProviderB::try_compute(context, code, intermediary)
42 }
43}
44
45#[cgp_provider]
46impl<Context, Code, Input, ProviderA, ProviderB> AsyncComputer<Context, Code, Input>
47 for ComposeHandlers<ProviderA, ProviderB>
48where
49 ProviderA: AsyncComputer<Context, Code, Input>,
50 ProviderB: AsyncComputer<Context, Code, ProviderA::Output>,
51{
52 type Output = ProviderB::Output;
53
54 async fn compute_async(
55 context: &Context,
56 code: PhantomData<Code>,
57 input: Input,
58 ) -> Self::Output {
59 let intermediary = ProviderA::compute_async(context, code, input).await;
60 ProviderB::compute_async(context, code, intermediary).await
61 }
62}
63
64#[cgp_provider]
65impl<Context, Code, Input, ProviderA, ProviderB> Handler<Context, Code, Input>
66 for ComposeHandlers<ProviderA, ProviderB>
67where
68 Context: HasErrorType,
69 ProviderA: Handler<Context, Code, Input>,
70 ProviderB: Handler<Context, Code, ProviderA::Output>,
71{
72 type Output = ProviderB::Output;
73
74 async fn handle(
75 context: &Context,
76 code: PhantomData<Code>,
77 input: Input,
78 ) -> Result<Self::Output, Context::Error> {
79 let intermediary = ProviderA::handle(context, code, input).await?;
80 ProviderB::handle(context, code, intermediary).await
81 }
82}