Skip to main content

delegate_components

Macro delegate_components 

Source
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,
        ...
    }
}