cgp_dispatch/providers/field_matchers/
extract_handle.rs1use cgp_core::field::CanDowncastFields;
2use cgp_core::prelude::*;
3use cgp_handler::{
4 Computer, ComputerComponent, Handler, HandlerComponent, TryComputer, TryComputerComponent,
5};
6
7pub struct DowncastAndHandle<Input, Provider = UseContext>(pub PhantomData<(Input, Provider)>);
8
9#[cgp_provider]
10impl<Context, Code, Input, Provider, Inner, Output, Remainder> Computer<Context, Code, Input>
11 for DowncastAndHandle<Inner, Provider>
12where
13 Input: CanDowncastFields<Inner, Remainder = Remainder>,
14 Provider: Computer<Context, Code, Inner, Output = Output>,
15{
16 type Output = Result<Output, Remainder>;
17
18 fn compute(
19 context: &Context,
20 tag: PhantomData<Code>,
21 input: Input,
22 ) -> Result<Output, Remainder> {
23 let inner = input.downcast_fields(PhantomData::<Inner>)?;
24 let output = Provider::compute(context, tag, inner);
25 Ok(output)
26 }
27}
28
29#[cgp_provider]
30impl<Context, Code, Input, Provider, Inner, Output, Remainder> TryComputer<Context, Code, Input>
31 for DowncastAndHandle<Inner, Provider>
32where
33 Context: HasErrorType,
34 Input: CanDowncastFields<Inner, Remainder = Remainder>,
35 Provider: TryComputer<Context, Code, Inner, Output = Output>,
36{
37 type Output = Result<Output, Remainder>;
38
39 fn try_compute(
40 context: &Context,
41 tag: PhantomData<Code>,
42 input: Input,
43 ) -> Result<Result<Output, Remainder>, Context::Error> {
44 let inner = input.downcast_fields(PhantomData::<Inner>);
45
46 match inner {
47 Ok(inner) => {
48 let output = Provider::try_compute(context, tag, inner)?;
49 Ok(Ok(output))
50 }
51 Err(remainder) => Ok(Err(remainder)),
52 }
53 }
54}
55
56#[cgp_provider]
57impl<Context, Code: Send, Input: Send, Provider, Inner: Send, Output: Send, Remainder: Send>
58 Handler<Context, Code, Input> for DowncastAndHandle<Inner, Provider>
59where
60 Context: HasAsyncErrorType,
61 Input: CanDowncastFields<Inner, Remainder = Remainder>,
62 Provider: Handler<Context, Code, Inner, Output = Output>,
63{
64 type Output = Result<Output, Remainder>;
65
66 async fn handle(
67 context: &Context,
68 tag: PhantomData<Code>,
69 input: Input,
70 ) -> Result<Result<Output, Remainder>, Context::Error> {
71 let inner = input.downcast_fields(PhantomData::<Inner>);
72
73 match inner {
74 Ok(inner) => {
75 let output = Provider::handle(context, tag, inner).await?;
76 Ok(Ok(output))
77 }
78 Err(remainder) => Ok(Err(remainder)),
79 }
80 }
81}