cgp_handler/providers/
pipe.rs

1use core::marker::PhantomData;
2
3use cgp_core::prelude::*;
4
5use crate::components::*;
6
7pub struct PipeHandlers<Providers>(pub PhantomData<Providers>);
8
9#[cgp_provider]
10impl<Context, Code, Input, Output, Providers> Handler<Context, Code, Input>
11    for PipeHandlers<Providers>
12where
13    Context: HasAsyncErrorType,
14    Providers: PipeHandler<Context, Code, Input, Output = Output>,
15    Code: Send,
16    Input: Send,
17    Output: Send,
18{
19    type Output = Output;
20
21    async fn handle(
22        context: &Context,
23        tag: PhantomData<Code>,
24        input: Input,
25    ) -> Result<Output, Context::Error> {
26        Providers::handle(context, tag, input).await
27    }
28}
29
30#[cgp_provider]
31impl<Context, Tag, Input, Output, Providers> TryComputer<Context, Tag, Input>
32    for PipeHandlers<Providers>
33where
34    Context: HasErrorType,
35    Providers: PipeTryComputer<Context, Tag, Input, Output = Output>,
36{
37    type Output = Output;
38
39    fn try_compute(
40        context: &Context,
41        tag: PhantomData<Tag>,
42        input: Input,
43    ) -> Result<Output, Context::Error> {
44        Providers::try_compute(context, tag, input)
45    }
46}
47
48#[cgp_provider]
49impl<Context, Tag, Input, Output, Providers> Computer<Context, Tag, Input>
50    for PipeHandlers<Providers>
51where
52    Providers: PipeComputer<Context, Tag, Input, Output = Output>,
53{
54    type Output = Output;
55
56    fn compute(context: &Context, tag: PhantomData<Tag>, input: Input) -> Output {
57        Providers::compute(context, tag, input)
58    }
59}
60
61#[async_trait]
62trait PipeHandler<Context, Code, Input>
63where
64    Context: HasAsyncErrorType,
65{
66    type Output;
67
68    async fn handle(
69        context: &Context,
70        _code: PhantomData<Code>,
71        input: Input,
72    ) -> Result<Self::Output, Context::Error>;
73}
74
75impl<Context, Code, Input, Output, CurrentProvider, RestProviders> PipeHandler<Context, Code, Input>
76    for Cons<CurrentProvider, RestProviders>
77where
78    Context: HasAsyncErrorType,
79    CurrentProvider: Handler<Context, Code, Input>,
80    RestProviders: PipeHandler<Context, Code, CurrentProvider::Output, Output = Output>,
81    Code: Send,
82    Input: Send,
83    Output: Send,
84{
85    type Output = Output;
86
87    async fn handle(
88        context: &Context,
89        tag: PhantomData<Code>,
90        input: Input,
91    ) -> Result<Output, Context::Error> {
92        let intermediate = CurrentProvider::handle(context, tag, input).await?;
93        RestProviders::handle(context, tag, intermediate).await
94    }
95}
96
97impl<Context, Code, Input> PipeHandler<Context, Code, Input> for Nil
98where
99    Context: HasAsyncErrorType,
100    Code: Send,
101    Input: Send,
102{
103    type Output = Input;
104
105    async fn handle(
106        _context: &Context,
107        _code: PhantomData<Code>,
108        input: Input,
109    ) -> Result<Input, Context::Error> {
110        Ok(input)
111    }
112}
113
114trait PipeTryComputer<Context, Code, Input>
115where
116    Context: HasErrorType,
117{
118    type Output;
119
120    fn try_compute(
121        context: &Context,
122        _code: PhantomData<Code>,
123        input: Input,
124    ) -> Result<Self::Output, Context::Error>;
125}
126
127impl<Context, Tag, Input, Output, CurrentProvider, RestProviders>
128    PipeTryComputer<Context, Tag, Input> for Cons<CurrentProvider, RestProviders>
129where
130    Context: HasErrorType,
131    CurrentProvider: TryComputer<Context, Tag, Input>,
132    RestProviders: PipeTryComputer<Context, Tag, CurrentProvider::Output, Output = Output>,
133{
134    type Output = Output;
135
136    fn try_compute(
137        context: &Context,
138        tag: PhantomData<Tag>,
139        input: Input,
140    ) -> Result<Output, Context::Error> {
141        let intermediate = CurrentProvider::try_compute(context, tag, input)?;
142        RestProviders::try_compute(context, tag, intermediate)
143    }
144}
145
146impl<Context, Code, Input> PipeTryComputer<Context, Code, Input> for Nil
147where
148    Context: HasErrorType,
149{
150    type Output = Input;
151
152    fn try_compute(
153        _context: &Context,
154        _code: PhantomData<Code>,
155        input: Input,
156    ) -> Result<Input, Context::Error> {
157        Ok(input)
158    }
159}
160
161trait PipeComputer<Context, Code, Input> {
162    type Output;
163
164    fn compute(context: &Context, _code: PhantomData<Code>, input: Input) -> Self::Output;
165}
166
167impl<Context, Tag, Input, Output, CurrentProvider, RestProviders> PipeComputer<Context, Tag, Input>
168    for Cons<CurrentProvider, RestProviders>
169where
170    CurrentProvider: Computer<Context, Tag, Input>,
171    RestProviders: PipeComputer<Context, Tag, CurrentProvider::Output, Output = Output>,
172{
173    type Output = Output;
174
175    fn compute(context: &Context, tag: PhantomData<Tag>, input: Input) -> Output {
176        let intermediate = CurrentProvider::compute(context, tag, input);
177        RestProviders::compute(context, tag, intermediate)
178    }
179}
180
181impl<Context, Code, Input> PipeComputer<Context, Code, Input> for Nil {
182    type Output = Input;
183
184    fn compute(_context: &Context, _code: PhantomData<Code>, input: Input) -> Input {
185        input
186    }
187}