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>);