delegate_components!() { /* proc-macro */ }Expand description
The delegate_components! macro is used to define wiring of CGP components
on a provider type.
§Type-Level Maps
Conceptually, we can think of the use of delegate_components! as defining a
type-level map, with the keys and values being types. When the keys are the
CGP component name types and the values are the CGP providers, then
delegate_components! is effectively implementing the specified providers
on the target type by delegating them to the providers specified in the
type-level map.
The macro is implemented by having the target type implement the DelegateComponent
trait, with the key used in the Name parameter and the value being set as the
Delegate associated type.
Additionally, for each key/value entry, the macro also generates implementation for
the IsProviderFor trait, which would be used during provider trait implementation
to propagate any unsatisfied constraints error to be shown to the user.
§Basic Syntax
In its most basic form, the macro can be used by specifying a list of key/value pairs as follows:
delegate_components! {
MyComponents {
KeyA: ValueA,
KeyB: ValueB,
...
}
}This would turn the target type into a type-level map, which would contain the entries
KeyA -> ValueA, KeyB -> ValueB, etc. For each Key and Value, the macro
would generate the following implementation:
impl DelegateComponent<Key> for MyComponents
{
type Delegate = Value;
}
impl<Context, Params> IsProviderFor<Key, Context, Params> for Value
where
Value: IsProviderFor<Key, Context, Params>,
{
}§Grouping Keys
The macro also supports grouping multiple keys together using the list syntax, when the grouped keys all map to the same value. This is useful when we want to delegate multiple CGP components to the same target provider.
For example, given the following:
delegate_components! {
MyComponents {
[
KeyA,
KeyB,
...
]:
Value,
}
}It would be equivalent to the following:
delegate_components! {
MyComponents {
KeyA: Value,
KeyB: Value,
...
}
}§Generating Mapping Struct
By default, mapping types like MyComponents would be defined outside of delegate_components!
as a dummy struct, or generated through other macros such as #[cgp_context]. However,
delegate_components! also accepts an optional new keyword in front of the map type,
in which it would also generate the struct definition for the mapping type.
For example, given the following:
delegate_components! {
new MyComponents {
KeyA: ValueA,
KeyB: ValueB,
...
}
}The macro would also generate the MyComponents struct as follows:
pub struct MyComponents;§Inner Maps
When defining component wiring that involves inner maps, such as with the use of
UseDelegate, delegate_components! also supports defining the inner map type
as well as the definition of inner key/value pairs all within the same macro invocation.
For example, given the following:
delegate_components! {
MyComponents {
OuterKey: UseDelegate<new InnerMap {
InnerKeyA: InnerValueA,
InnerKeyB: InnerValueB,
...
}>,
}
}It would be the same as writing two separate calls to delegate_components! as follows:
delegate_components! {
MyComponents {
OuterKey: UseDelegate<InnerMap>,
}
}
delegate_components! {
new InnerMap {
InnerKeyA: InnerValueA,
InnerKeyB: InnerValueB,
...
}
}