Macro plugin_model

Source
macro_rules! plugin_model {
    (@output_ty $Input:tt) => { ... };
    (@output_ty $Input:tt, $Output:tt) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: $Input:ident,
        $(output: $Output:ident ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: $Input:ident,
        $(output: ($($Output:ident),+) ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: ($($Input:ident),+),
        $(output: $Output:ident ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: ($($Input:ident),+),
        $(output: ($($Output:ident),+) ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: $Input:ident,
        $(output: $Output:ident ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        context: $Context:ty,
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: $Input:ident,
        $(output: ($($Output:ident),+) ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        context: $Context:ty,
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: ($($Input:ident),+),
        $(output: $Output:ident ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        context: $Context:ty,
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: ($($Input:ident),+),
        $(output: ($($Output:ident),+) ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        context: $Context:ty,
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: mut $Input:ident,
        $(output: $Output:ident ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: mut $Input:ident,
        $(output: ($($Output:ident),+) ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: mut ($($Input:ident),+),
        $(output: $Output:ident ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: mut ($($Input:ident),+),
        $(output: ($($Output:ident),+) ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: mut $Input:ident,
        $(output: $Output:ident ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        context: $Context:ty,
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: mut $Input:ident,
        $(output: ($($Output:ident),+) ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        context: $Context:ty,
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: mut ($($Input:ident),+),
        $(output: $Output:ident ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        context: $Context:ty,
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
    (
        $(#[$name_meta:meta])*
        name: $vis:vis $ModelName:ident,
        input: mut ($($Input:ident),+),
        $(output: ($($Output:ident),+) ,)?
        $(others: [$($other_gen:tt),* $(,)? ] ,)?
        context: $Context:ty,
        bounds: [$($bounds:tt)*],
        $(#[$compute_meta:meta])*
        compute: |$input_arg:ident, $ctx_arg:ident| $body:block $(,)?
    ) => { ... };
}
Expand description

Defines a plugin model in a fully generic, and type-safe way.

The macro generates:

This removes repetitive boilerplate while ensuring that the relationships between input, output, and context types are enforced at compile time.

Exactly one of:

  • input: -> immutable model (PurePluginModel)
  • input: mut -> mutable model (MutablePluginModel)

Optionally:

  • context: enables contextual execution (otherwise context defaults to ())
  • root: + child: attaches the model to a plugin family for late resolution

§Syntax

§Immutable Model (No Context)

plugin_model! {
    name: pub ModelName,          // Required: struct visibility and struct name of the plugin model
    input: InputType,             // Required: generic immutable input type
    output: OutputType,           // Optional: output type (defaults to input if omitted)
    others: [T1, T2],             // Optional: additional generic parameters
    bounds: [TraitBounds],        // Required: trait bounds for generics
    compute: |input, ctx| { ... } // Required: compute logic (`ctx` is `()`)
}

§Immutable Model with Context

plugin_model! {
    name: pub ModelName,          // Required: struct visibility and struct name of the plugin model
    input: InputType,             // Required: generic immutable input type
    output: OutputType,           // Optional: output type (defaults to input if omitted)
    others: [T1, T2],             // Optional: additional generic parameters
    context: ContextType,         // Required: context struct used during execution
    bounds: [TraitBounds],        // Required: trait bounds for generics
    compute: |input, ctx| { ... } // `ctx: &ContextType`
}

§Mutable Model

plugin_model! {
    name: pub ModelName,          // Required: struct visibility and struct name of the plugin model
    input: mut InputType,         // Required: mutable input type (`&mut InputType`)
    output: OutputType,           // Optional: output type (defaults to immutable input type)
    others: [T1, T2],             // Optional: additional generic parameters
    context: ContextType,         // Optional: context struct (defaults to `()`)
    bounds: [TraitBounds],        // Required: trait bounds for generics
    compute: |input, ctx| { ... } // Uses `compute_mut`
}

§Output Type Semantics

  • If output is omitted, the output type defaults to the immutable input type, even for mutable models (it does not default to ()).
  • This rule applies to both immutable and mutable plugin models.
  • If a unit output () is desired, it must be specified explicitly as:
output: Output,
bounds: [Output: Default]

The Default bound is required so compute’s block can construct the output value.

§Semantics

  • Each model is fully generic over its input, output, and optional context.
  • If context is omitted, the model uses () as its context type.
  • If root and child are provided, the model becomes a member of a plugin family and is selected indirectly using the (root, child, context) resolution lattice.
  • Immutable variants use compute with shared input references.
  • Mutable variants use compute_mut and may mutate the input in-place.

All constraints are enforced purely through trait bounds and associated types, guaranteeing compile-time correctness of model wiring and resolution.