modulink_rs/
macros.rs

1//! Modulink-RS Macro Implementations
2//
3// This file implements all macros and patterns described in the macro reference and documentation.
4// Each macro is annotated with usage and rationale. See docs/MODULINK_MACROS.md for details.
5
6// ---
7// 1. Context Macro
8//
9// Purpose: Define or initialize a context (can be `Context`, `MutableContext`, or custom type).
10//
11/*
12/// Macro to define a context struct with named fields.
13///
14/// # Example
15/// ```rust
16/// define_context! {
17///     user_id: u64,
18///     data: String,
19/// }
20/// let ctx = Context::new();
21/// ```
22///
23/// Use this macro to quickly define a context type for your chain.
24#[macro_export]
25macro_rules! define_context {
26    ( $( $field:ident : $ty:ty ),* $(,)? ) => {
27        #[derive(Debug, Clone, Default)]
28        pub struct Context {
29            $( pub $field: $ty, )*
30        }
31        impl Context {
32            pub fn new() -> Self { Self { $( $field: Default::default(), )* } }
33        }
34    };
35}
36*/
37
38// ---
39// 2. Link Macro
40//
41// Purpose: Define a link as a pure async function or closure.
42//
43/*
44/// Macro to define a link as a pure async function or closure.
45///
46/// # Function-style Example
47/// ```rust
48/// link! {
49///     fn add_user_id(ctx: Context) -> Context {
50///         ctx.insert("user_id", 42)
51///     }
52/// }
53/// ```
54///
55/// # Closure-style Example
56/// ```rust
57/// let link = link!(|ctx: Context| async move { ctx.insert("user_id", 42) });
58/// ```
59///
60/// Use this macro to define composable steps in your chain.
61#[macro_export]
62macro_rules! link {
63    // Function-style link
64    (fn $name:ident ( $ctx:ident : $ctx_ty:ty ) -> $ret:ty $body:block) => {
65        pub async fn $name($ctx: $ctx_ty) -> $ret $body
66    };
67    // Closure-style link
68    (|$ctx:ident : $ctx_ty:ty| $body:expr) => {
69        Box::new(move |$ctx: $ctx_ty| Box::pin(async move { $body }))
70    };
71}
72*/
73
74// ---
75// 3. Chain Macro (active)
76//
77// Purpose: Compose a sequence of links into a chain.
78//
79/// Macro to compose a sequence of links into a chain.
80///
81/// # Example
82/// ```rust
83/// use modulink_rs::chain;
84/// use std::sync::Arc;
85/// use std::future::Future;
86/// use std::pin::Pin;
87/// use modulink_rs::context::Context;
88/// // Example async link type for Chain
89/// let link1: Arc<dyn Fn(Context) -> Pin<Box<dyn Future<Output = Context> + Send>> + Send + Sync> = Arc::new(|ctx: Context| Box::pin(async move { ctx }));
90/// let link2 = link1.clone();
91/// let link3 = link1.clone();
92/// // Comma-separated syntax
93/// let my_chain = chain!(link1.clone(), link2.clone(), link3.clone());
94/// // Array-like syntax
95/// let my_chain2 = chain![link1.clone(), link2.clone(), link3.clone()];
96/// // my_chain can now be executed with .run(ctx).await
97/// ```
98///
99/// Use this macro to build a pipeline of links.
100#[macro_export]
101macro_rules! chain {
102    // Generic: explicit type parameter (array syntax)
103    [type = $ty:ty; $( $link:expr ),* $(,)? ] => {
104        {
105            let mut c = ::modulink_rs::chains::ChainGeneric::<$ty>::new();
106            $( c.add_link($link); )*
107            c
108        }
109    };
110    // Generic: explicit type parameter (comma syntax)
111    (type = $ty:ty; $( $link:expr ),* $(,)? ) => {
112        {
113            let mut c = ::modulink_rs::chains::ChainGeneric::<$ty>::new();
114            $( c.add_link($link); )*
115            c
116        }
117    };
118    // Ergonomic: default Context (comma-separated list)
119    ( $( $link:expr ),* $(,)? ) => {
120        {
121            let mut c = ::modulink_rs::chains::Chain::new();
122            $( c.add_link($link); )*
123            c
124        }
125    };
126    // Ergonomic: default Context (array-like syntax)
127    [ $( $link:expr ),* $(,)? ] => {
128        {
129            let mut c = ::modulink_rs::chains::Chain::new();
130            $( c.add_link($link); )*
131            c
132        }
133    };
134}
135
136// ---
137// 4. Add Link Macro (method pattern)
138//
139// Purpose: Add a link to an existing chain.
140//
141// Usage:
142// my_chain.add_link(link!(|ctx| async move { ctx }));
143//
144// Rationale: Enables dynamic or incremental chain construction.
145
146// ---
147// 5. Use Middleware Macro (method pattern)
148//
149// Purpose: Attach middleware for logging, metrics, or side effects.
150//
151// Usage:
152// my_chain.use_middleware(middleware!(Logging));
153//
154// Rationale: Middleware provides observability and cross-cutting concerns.
155
156// ---
157// 6. Connect Macro (Branching)
158//
159// Purpose: Add conditional branches between links or chains, using a macro syntax that clarifies intent and supports both link and chain connections.
160//
161/*
162/// Macro to add conditional branches between links or chains.
163///
164/// # Syntax
165/// - Connect a link:
166///   ```rust
167///   my_chain.connect![
168///       link: my_link,
169///       to: link_in_og_chain,
170///       when: condition!(|ctx| ctx.get::<bool>("skip").unwrap_or(false)),
171///   ]
172///   ```
173/// - Connect a chain:
174///   ```rust
175///   my_chain.connect![
176///       chain: my_other_chain,
177///       to: link_in_og_chain,
178///       when: condition!(|ctx| ctx.get::<bool>("should_branch").unwrap_or(false)),
179///   ]
180///   ```
181///
182/// Use this macro to enable advanced graph topologies, error routing, and dynamic control flow.
183#[macro_export]
184macro_rules! connect {
185    (
186        link: $link:expr,
187        to: $to:expr,
188        when: $when:expr $(,)?
189    ) => {
190        .connect_link($link, $to, $when)
191    };
192    (
193        chain: $chain:expr,
194        to: $to:expr,
195        when: $when:expr $(,)?
196    ) => {
197        .connect_chain($chain, $to, $when)
198    };
199}
200*/
201
202// ---
203// 7. Run Macro (method pattern)
204//
205// Purpose: Execute the chain with a given context.
206//
207// Usage:
208// let result = my_chain.run(ctx).await;
209//
210// Rationale: Runs the pipeline. Async for concurrency.
211
212// ---
213// 8. Condition Macro
214//
215// Purpose: Define a branching condition as a closure.
216//
217/*
218/// Macro to define a branching condition as a closure.
219///
220/// # Example
221/// ```rust
222/// let cond = condition!(|ctx: &Context| ctx.get::<bool>("flag").unwrap_or(false));
223/// ```
224///
225/// Use this macro for branching and control flow in chains.
226#[macro_export]
227macro_rules! condition {
228    (|$ctx:ident : $ctx_ty:ty| $body:expr) => {
229        Box::new(move |$ctx: &$ctx_ty| $body)
230    };
231    (|$ctx:ident| $body:expr) => {
232        Box::new(move |$ctx| $body)
233    };
234}
235*/
236
237// ---
238// 9. Middleware Macro
239//
240// Purpose: Define custom middleware with before/after hooks.
241//
242/*
243/// Macro to define custom middleware with before/after hooks.
244///
245/// # Example
246/// ```rust
247/// middleware! {
248///     struct MyLogger;
249///     impl Middleware for MyLogger {
250///         async fn before(&self, ctx: &dyn std::any::Any) {
251///             println!("Before link");
252///         }
253///         async fn after(&self, ctx: &dyn std::any::Any) {
254///             println!("After link");
255///         }
256///     }
257/// }
258/// ```
259///
260/// Use this macro to add observability, metrics, or side effects.
261#[macro_export]
262macro_rules! middleware {
263    // Struct + impl block
264    (struct $name:ident; impl Middleware for $name2:ident { $($body:tt)* }) => {
265        pub struct $name;
266        #[async_trait::async_trait]
267        impl ::modulink_rs::middleware::Middleware for $name2 {
268            $($body)*
269        }
270    };
271}
272*/
273
274// ---
275// 10. Listener Macro
276//
277// Purpose: Define a listener for triggers (HTTP, CLI, etc.).
278//
279/*
280/// Macro to define a listener for triggers (HTTP, CLI, etc.).
281///
282/// # Example
283/// ```rust
284/// listener! {
285///     struct MyHttpListener;
286///     // ... implement listener trait ...
287/// }
288/// ```
289///
290/// Use this macro to integrate chains with external systems.
291#[macro_export]
292macro_rules! listener {
293    (struct $name:ident; $($body:tt)*) => {
294        pub struct $name;
295        $($body)*
296    };
297}
298*/
299
300// ---
301// Notes:
302// - All macros are sketches; adapt as needed for your codebase.
303// - Use shadowing (`let ctx = ...`) for ergonomic APIs; use `mut` only for advanced/generic APIs and document the tradeoff.
304// - Maximize type safety, extensibility, and modularity as God wills.
305// - See docs/CHAIN_MACRO_PATTERNS.md and docs/CHEATSHEET_ADVANCED.md for more.