cgp_component/types/
use_delegate.rs

1use core::marker::PhantomData;
2
3/**
4    The `UseDelegate` pattern is used as the _default dispatcher_ for CGP
5    components that contain additional generic parameters in their traits.
6
7    When a provider trait contains additional generic parameters in addition
8    to the `Context` type, CGP can generate a `UseDelegate` implementation
9    that uses `Components` as a _type-level lookup table_ to dispatch the
10    implementation to different providers based on the generic types.
11
12    The implementation of `UseDelegate` follows the same pattern as the
13    blanket implementation of a provider trait. However, instead of using
14    the component name type as the key, it uses the specified generic
15    parameters as the key to lookup the provider through `DelegateComponent`.
16
17    `UseDelegate` is very commonly used to perform ad hoc dispatch of
18    concrete types to different context-generic providers. This allows the
19    providers to remain generic, even when they may have implementations
20    that overlaps on the generic parameters.
21
22    The implementation of `UseDelegate` can be automatically generated through
23    the `derive_delegate` entry in `#[cgp_component]`. It is also possible to
24    implement the dispatcher pattern on types other than `UseDelegate`, especially
25    when there are multiple generic parameters that could be dispatched differently.
26    We mainly use `UseDelegate` as the default dispatcher, so that users don't need
27    to remember the different provider types to be used with each component.
28
29    ## Example
30
31    Given the following component definition:
32
33    ```rust,ignore
34    #[cgp_component {
35        provider: ErrorRaiser,
36        derive_delegate: UseDelegate<SourceError>,
37    }]
38    pub trait CanRaiseError<SourceError>: HasErrorType {
39        fn raise_error(error: SourceError) -> Self::Error;
40    }
41    ```
42
43    The following `UseDelegate` implementation would be generated:
44
45    ```rust,ignore
46    impl<Context, SourceError, Components, Delegate> ErrorRaiser<Context, SourceError>
47        for UseDelegate<Components>
48    where
49        Context: HasErrorType,
50        Components: DelegateComponent<(SourceError), Delegate = Delegate>,
51        Delegate: ErrorRaiser<Context, SourceError>,
52    {
53        fn raise_error(error: SourceError) -> Context::Error {
54            Delegate::raise_error(error)
55        }
56    }
57    ```
58*/
59pub struct UseDelegate<Components>(pub PhantomData<Components>);