modulink-rs 1.0.0

A modular, composable, and observable async function orchestration library for Rust, following the ModuLink universal template.
Documentation
//! Modulink-RS Macro Implementations
//
// This file implements all macros and patterns described in the macro reference and documentation.
// Each macro is annotated with usage and rationale. See docs/MODULINK_MACROS.md for details.

// ---
// 1. Context Macro
//
// Purpose: Define or initialize a context (can be `Context`, `MutableContext`, or custom type).
//
/*
/// Macro to define a context struct with named fields.
///
/// # Example
/// ```rust
/// define_context! {
///     user_id: u64,
///     data: String,
/// }
/// let ctx = Context::new();
/// ```
///
/// Use this macro to quickly define a context type for your chain.
#[macro_export]
macro_rules! define_context {
    ( $( $field:ident : $ty:ty ),* $(,)? ) => {
        #[derive(Debug, Clone, Default)]
        pub struct Context {
            $( pub $field: $ty, )*
        }
        impl Context {
            pub fn new() -> Self { Self { $( $field: Default::default(), )* } }
        }
    };
}
*/

// ---
// 2. Link Macro
//
// Purpose: Define a link as a pure async function or closure.
//
/*
/// Macro to define a link as a pure async function or closure.
///
/// # Function-style Example
/// ```rust
/// link! {
///     fn add_user_id(ctx: Context) -> Context {
///         ctx.insert("user_id", 42)
///     }
/// }
/// ```
///
/// # Closure-style Example
/// ```rust
/// let link = link!(|ctx: Context| async move { ctx.insert("user_id", 42) });
/// ```
///
/// Use this macro to define composable steps in your chain.
#[macro_export]
macro_rules! link {
    // Function-style link
    (fn $name:ident ( $ctx:ident : $ctx_ty:ty ) -> $ret:ty $body:block) => {
        pub async fn $name($ctx: $ctx_ty) -> $ret $body
    };
    // Closure-style link
    (|$ctx:ident : $ctx_ty:ty| $body:expr) => {
        Box::new(move |$ctx: $ctx_ty| Box::pin(async move { $body }))
    };
}
*/

// ---
// 3. Chain Macro (active)
//
// Purpose: Compose a sequence of links into a chain.
//
/// Macro to compose a sequence of links into a chain.
///
/// # Example
/// ```rust
/// use modulink_rs::chain;
/// use std::sync::Arc;
/// use std::future::Future;
/// use std::pin::Pin;
/// use modulink_rs::context::Context;
/// // Example async link type for Chain
/// let link1: Arc<dyn Fn(Context) -> Pin<Box<dyn Future<Output = Context> + Send>> + Send + Sync> = Arc::new(|ctx: Context| Box::pin(async move { ctx }));
/// let link2 = link1.clone();
/// let link3 = link1.clone();
/// // Comma-separated syntax
/// let my_chain = chain!(link1.clone(), link2.clone(), link3.clone());
/// // Array-like syntax
/// let my_chain2 = chain![link1.clone(), link2.clone(), link3.clone()];
/// // my_chain can now be executed with .run(ctx).await
/// ```
///
/// Use this macro to build a pipeline of links.
#[macro_export]
macro_rules! chain {
    // Generic: explicit type parameter (array syntax)
    [type = $ty:ty; $( $link:expr ),* $(,)? ] => {
        {
            let mut c = ::modulink_rs::chains::ChainGeneric::<$ty>::new();
            $( c.add_link($link); )*
            c
        }
    };
    // Generic: explicit type parameter (comma syntax)
    (type = $ty:ty; $( $link:expr ),* $(,)? ) => {
        {
            let mut c = ::modulink_rs::chains::ChainGeneric::<$ty>::new();
            $( c.add_link($link); )*
            c
        }
    };
    // Ergonomic: default Context (comma-separated list)
    ( $( $link:expr ),* $(,)? ) => {
        {
            let mut c = ::modulink_rs::chains::Chain::new();
            $( c.add_link($link); )*
            c
        }
    };
    // Ergonomic: default Context (array-like syntax)
    [ $( $link:expr ),* $(,)? ] => {
        {
            let mut c = ::modulink_rs::chains::Chain::new();
            $( c.add_link($link); )*
            c
        }
    };
}

// ---
// 4. Add Link Macro (method pattern)
//
// Purpose: Add a link to an existing chain.
//
// Usage:
// my_chain.add_link(link!(|ctx| async move { ctx }));
//
// Rationale: Enables dynamic or incremental chain construction.

// ---
// 5. Use Middleware Macro (method pattern)
//
// Purpose: Attach middleware for logging, metrics, or side effects.
//
// Usage:
// my_chain.use_middleware(middleware!(Logging));
//
// Rationale: Middleware provides observability and cross-cutting concerns.

// ---
// 6. Connect Macro (Branching)
//
// Purpose: Add conditional branches between links or chains, using a macro syntax that clarifies intent and supports both link and chain connections.
//
/*
/// Macro to add conditional branches between links or chains.
///
/// # Syntax
/// - Connect a link:
///   ```rust
///   my_chain.connect![
///       link: my_link,
///       to: link_in_og_chain,
///       when: condition!(|ctx| ctx.get::<bool>("skip").unwrap_or(false)),
///   ]
///   ```
/// - Connect a chain:
///   ```rust
///   my_chain.connect![
///       chain: my_other_chain,
///       to: link_in_og_chain,
///       when: condition!(|ctx| ctx.get::<bool>("should_branch").unwrap_or(false)),
///   ]
///   ```
///
/// Use this macro to enable advanced graph topologies, error routing, and dynamic control flow.
#[macro_export]
macro_rules! connect {
    (
        link: $link:expr,
        to: $to:expr,
        when: $when:expr $(,)?
    ) => {
        .connect_link($link, $to, $when)
    };
    (
        chain: $chain:expr,
        to: $to:expr,
        when: $when:expr $(,)?
    ) => {
        .connect_chain($chain, $to, $when)
    };
}
*/

// ---
// 7. Run Macro (method pattern)
//
// Purpose: Execute the chain with a given context.
//
// Usage:
// let result = my_chain.run(ctx).await;
//
// Rationale: Runs the pipeline. Async for concurrency.

// ---
// 8. Condition Macro
//
// Purpose: Define a branching condition as a closure.
//
/*
/// Macro to define a branching condition as a closure.
///
/// # Example
/// ```rust
/// let cond = condition!(|ctx: &Context| ctx.get::<bool>("flag").unwrap_or(false));
/// ```
///
/// Use this macro for branching and control flow in chains.
#[macro_export]
macro_rules! condition {
    (|$ctx:ident : $ctx_ty:ty| $body:expr) => {
        Box::new(move |$ctx: &$ctx_ty| $body)
    };
    (|$ctx:ident| $body:expr) => {
        Box::new(move |$ctx| $body)
    };
}
*/

// ---
// 9. Middleware Macro
//
// Purpose: Define custom middleware with before/after hooks.
//
/*
/// Macro to define custom middleware with before/after hooks.
///
/// # Example
/// ```rust
/// middleware! {
///     struct MyLogger;
///     impl Middleware for MyLogger {
///         async fn before(&self, ctx: &dyn std::any::Any) {
///             println!("Before link");
///         }
///         async fn after(&self, ctx: &dyn std::any::Any) {
///             println!("After link");
///         }
///     }
/// }
/// ```
///
/// Use this macro to add observability, metrics, or side effects.
#[macro_export]
macro_rules! middleware {
    // Struct + impl block
    (struct $name:ident; impl Middleware for $name2:ident { $($body:tt)* }) => {
        pub struct $name;
        #[async_trait::async_trait]
        impl ::modulink_rs::middleware::Middleware for $name2 {
            $($body)*
        }
    };
}
*/

// ---
// 10. Listener Macro
//
// Purpose: Define a listener for triggers (HTTP, CLI, etc.).
//
/*
/// Macro to define a listener for triggers (HTTP, CLI, etc.).
///
/// # Example
/// ```rust
/// listener! {
///     struct MyHttpListener;
///     // ... implement listener trait ...
/// }
/// ```
///
/// Use this macro to integrate chains with external systems.
#[macro_export]
macro_rules! listener {
    (struct $name:ident; $($body:tt)*) => {
        pub struct $name;
        $($body)*
    };
}
*/

// ---
// Notes:
// - All macros are sketches; adapt as needed for your codebase.
// - Use shadowing (`let ctx = ...`) for ergonomic APIs; use `mut` only for advanced/generic APIs and document the tradeoff.
// - Maximize type safety, extensibility, and modularity as God wills.
// - See docs/CHAIN_MACRO_PATTERNS.md and docs/CHEATSHEET_ADVANCED.md for more.