Macro define_family

Source
macro_rules! define_family {
    (@output_ty $Input:tt) => { ... };
    (@output_ty $Input:tt, $Output:tt) => { ... };
    (
        root: $Root:ident,
        $(#[$meta:meta])*
        family: $vis:vis $Name:ident,
        $(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
        input: $Input:ident,
        $(output: $Output:ident ,)?
        context: $Context:ty,
        $(marker: [$($marker_gen:ident),* $(,)?],)?
        $(bounds: [$($bounds:tt)*],)?
        child: [
            $($child:ident => $model:ty,)+
        $(,)? ] $(,)?
    ) => { ... };
    (
        root: $Root:ident,
        $(#[$meta:meta])*
        family: $vis:vis $Name:ident,
        $(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
        input: $Input:ident,
        $(output: ($($Output:ident),+) ,)?
        context: $Context:ty,
        $(marker: [$($marker_gen:ident),* $(,)?],)?
        $(bounds: [$($bounds:tt)*],)?
        child: [
            $($child:ident => $model:ty,)+
        $(,)? ] $(,)?
    ) => { ... };
    (
        root: $Root:ident,
        $(#[$meta:meta])*
        family: $vis:vis $Name:ident,
        $(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
        input: ($($Input:ident),+),
        $(output: $Output:ident ,)?
        context: $Context:ty,
        $(marker: [$($marker_gen:ident),* $(,)?],)?
        $(bounds: [$($bounds:tt)*],)?
        child: [
            $($child:ident => $model:ty,)+
        $(,)? ] $(,)?
    ) => { ... };
    (
        root: $Root:ident,
        $(#[$meta:meta])*
        family: $vis:vis $Name:ident,
        $(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
        input: ($($Input:ident),+),
        $(output: ($($Output:ident),+) ,)?
        context: $Context:ty,
        $(marker: [$($marker_gen:ident),* $(,)?],)?
        $(bounds: [$($bounds:tt)*],)?
        child: [
            $($child:ident => $model:ty,)+
        $(,)? ] $(,)?
    ) => { ... };
    (
        root: $Root:ident,
        $(#[$meta:meta])*
        family: $vis:vis $Name:ident,
        $(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
        input: $Input:ident,
        $(output: $Output:ident ,)?
        $(bounds: [$($bounds:tt)*],)?
        child: [
            $($child:ident => $model:ty,)+
        $(,)? ] $(,)?
    ) => { ... };
    (
        root: $Root:ident,
        $(#[$meta:meta])*
        family: $vis:vis $Name:ident,
        $(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
        input: $Input:ident,
        $(output: ($($Output:ident),+) ,)?
        $(bounds: [$($bounds:tt)*],)?
        child: [
            $($child:ident => $model:ty,)+
        $(,)? ] $(,)?
    ) => { ... };
    (
        root: $Root:ident,
        $(#[$meta:meta])*
        family: $vis:vis $Name:ident,
        $(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
        input: ($($Input:ident),+),
        $(output: $Output:ident ,)?
        $(bounds: [$($bounds:tt)*],)?
        child: [
            $($child:ident => $model:ty,)+
        $(,)? ] $(,)?
    ) => { ... };
    (
        root: $Root:ident,
        $(#[$meta:meta])*
        family: $vis:vis $Name:ident,
        $(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
        input: ($($Input:ident),+),
        $(output: ($($Output:ident),+) ,)?
        $(bounds: [$($bounds:tt)*],)?
        child: [
            $($child:ident => $model:ty,)+
        $(,)? ] $(,)?
    ) => { ... };
}
Expand description

Declares a concrete plugin family implementation for a given family root.

This macro generates:

  1. A family marker struct representing a concrete implementation of a plugin family.
  2. An implementation of the family root trait mapping each declared child operation to a concrete plugin model.

The generated family struct is purely a type-level marker and contains no runtime data. It is used to bind concrete plugin models to a specific (FamilyType, Child) combination through associated types.

When borrow are specified, the generated family marker stores them in PhantomData fields so the type system correctly tracks them without affecting runtime behavior.

§Syntax

§Family With Context

define_family! {
    root: FamilyRoot,             // Required: family root trait

    family: pub MyFamily,         // Required: visibility and concrete family marker struct
    borrow: ['a],                 // Optional: lifetime parameters for family marker

    input: Input,                 // Required: input type parameter
    output: Output,               // Optional: output type (defaults to input if omitted)

    context: MyContext,           // Required: context type
    marker: [T],                  // Optional: generic parameters for the context

    bounds: [T: Clone],           // Optional: trait bounds for the generated impl

    child: [                      // Required: child -> model mapping
        OperationA => ModelA,
        OperationB => ModelB,
    ]
}

§Family Without Context

define_family! {
    root: FamilyRoot,           // Required: family root trait

    family: pub MyFamily,       // Required: visibility and concrete family marker struct
    borrow: ['a],               // Optional: lifetime parameters for family marker

    input: Input,               // Required: input type parameter
    output: Output,             // Optional: output type (defaults to input if omitted)

    bounds: [T: Clone],         // Optional: trait bounds for the generated impl

    child: [                    // Required: child -> model mapping
        OperationA => ModelA,
        OperationB => ModelB,
    ]
}

In the second form, the context parameter of the root trait defaults to ().

§Lifetimes and Generics

  • borrow apply to the family marker type
    • used to model execution-time borrowing
    • stored via PhantomData
borrow: ['a]
  • marker apply only when a context is specified
    • used to parameterize the context type
    • introduced on the generated impl, not the family struct
context: MyContext,
marker: [T]

When no context is provided:

  • the context defaults to ()
  • marker is not used

§Example


// ----- Crate A ------

declare_family! {
    root: pub VotingFamily,
    child: [Phragmen, STV]
}

// ----- Crate B ------

plugin_model! {
    name: PhragmenModel,
    ...
}

plugin_model! {
    name: STVModel,
    ...
}

define_family! {
    root: VotingFamily,

    family: pub RuntimeVoting,
    input: AccountId,
    output: Balance,
    context: RuntimeContext,

    child: [
        Phragmen => PhragmenModel,
        STV => STVModel,
    ]
}

This binds the Phragmen and Approval operations of the VotingFamily root to concrete plugin models for the RuntimeVoting family implementation.