cgp_component/providers/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]` attribute 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(ErrorRaiser)]
35 #[derive_delegate(UseDelegate<SourceError>)]
36 pub trait CanRaiseError<SourceError>: HasErrorType {
37 fn raise_error(error: SourceError) -> Self::Error;
38 }
39 ```
40
41 The following `UseDelegate` implementation would be generated:
42
43 ```rust,ignore
44 impl<Context, SourceError, Components, Delegate> ErrorRaiser<Context, SourceError>
45 for UseDelegate<Components>
46 where
47 Context: HasErrorType,
48 Components: DelegateComponent<(SourceError), Delegate = Delegate>,
49 Delegate: ErrorRaiser<Context, SourceError>,
50 {
51 fn raise_error(error: SourceError) -> Context::Error {
52 Delegate::raise_error(error)
53 }
54 }
55 ```
56*/
57pub struct UseDelegate<Components>(pub PhantomData<Components>);