type_flow_macros/
lib.rs

1#[allow(unused_imports)]
2use type_flow_traits::{
3    Processor,
4    InPlaceProcessor,
5    TransformProcessor,
6    StatefulProcessor,
7    InPlaceStatefulProcessor,
8    Reverse,
9    ShiftLeft,
10    ShiftRight,
11    SwapStartEnd
12};
13/*macro_rules! count_tts {
14    () => { 0 };
15    ($odd:tt $($a:tt $b:tt)*) => { (count_tts!($($a)*) << 1) | 1 };
16    ($($a:tt $even:tt)*) => { count_tts!($($a)*) << 1 };
17}*/
18
19/// Creates a stateless, data-transforming processor struct.
20///
21/// This macro generates a struct that implements the `Processor<T>` trait,
22/// taking data of a specific type, processing it with a given function,
23/// and returning data of the same type.
24///
25/// # Parameters
26/// - `$struct_name`: The name for the new processor struct.
27/// - `$type`: The type of data the processor will operate on.
28/// - `$process_fn`: A function or closure that takes a value of `$type` and returns a new value of `$type`.
29///
30/// # Examples
31///
32/// ```
33/// use type_flow_macros::processor;
34/// use type_flow_traits::Processor;
35///
36/// fn to_uppercase(s: String) -> String {
37///     s.to_uppercase()
38/// }
39///
40/// processor!(UppercaseProcessor, String, to_uppercase);
41///
42/// let processed = UppercaseProcessor::process("hello".to_string());
43/// assert_eq!(processed, "HELLO");
44/// ```
45#[macro_export]
46macro_rules! processor {
47    ($struct_name:ident, $type:ty, $process_fn:expr) => {
48        pub struct $struct_name;
49        impl Processor<$type> for $struct_name {
50            fn process(data: $type) -> $type {
51                ($process_fn)(data)
52            }
53        }
54    };
55}
56
57/// Creates a stateless pipeline of processors.
58///
59/// This macro generates a struct that chains multiple `Processor` implementations
60/// together into a single pipeline. The data flows through each processor in the
61/// order they are specified.
62///
63/// # Parameters
64/// - `$struct_name`: The name for the new pipeline struct.
65/// - `$type`: The type of data the pipeline will operate on.
66/// - `$($processor: ty),+`: A comma-separated list of processor types that implement `Processor<$type>`.
67///
68/// # Examples
69///
70/// ```
71/// use type_flow_macros::{processor, processor_pipeline};
72/// use type_flow_traits::Processor;
73///
74/// processor!(AddOne, i32, |x| x + 1);
75/// processor!(MulTwo, i32, |x| x * 2);
76///
77/// processor_pipeline!(MyPipeline, i32, AddOne, MulTwo);
78///
79/// let result = MyPipeline::process(10);
80/// assert_eq!(result, 22); // (10 + 1) * 2
81/// ```
82#[macro_export]
83macro_rules! processor_pipeline {
84    ($struct_name:ident, $type:ty, $($processor:ty),+) => {
85        pub struct $struct_name;
86        impl Processor<$type> for $struct_name {
87            fn process(data: $type) -> $type {
88                let result = data;
89                $(
90                    let result = <$processor>::process(result);
91                )*
92                result
93            }
94        }
95    }
96}
97
98/// Creates a generic, stateless processor pipeline.
99///
100/// This macro generates a struct that is generic over its processors.
101/// It chains them together, and the pipeline itself implements `Processor`.
102/// This allows for creating flexible pipelines where the exact processors can
103/// be specified at a later time.
104///
105/// # Parameters
106/// - `$struct_name`: The name for the new generic pipeline struct.
107/// - `$processor_type`: The data type the pipeline operates on.
108/// - `$($type_param:ident),+`: A comma-separated list of generic type parameter identifiers.
109///   Each will be constrained to implement `Processor<$processor_type>`.
110///
111/// # Examples
112///
113/// ```
114/// use type_flow_macros::{processor, type_flow_processor_pipeline};
115/// use type_flow_traits::Processor;
116///
117/// processor!(AddTen, i32, |x| x + 10);
118/// processor!(DivTwo, i32, |x| x / 2);
119///
120/// type_flow_processor_pipeline!(GenericPipeline, i32, P1, P2);
121///
122/// let result = GenericPipeline::<AddTen, DivTwo>::process(20);
123/// assert_eq!(result, 15); // (20 + 10) / 2
124/// ```
125#[macro_export]
126macro_rules! type_flow_processor_pipeline {
127    ($struct_name:ident, $processor_type:ty, $($type_param:ident),+) => {
128        pub struct $struct_name<$($type_param: Processor<$processor_type>),*> {
129            _marker: std::marker::PhantomData<($($type_param),*)>,
130        }
131        impl<$($type_param: Processor<$processor_type>),*> Processor<$processor_type> for $struct_name<$($type_param),*> {
132            fn process(data: $processor_type) -> $processor_type{
133                let result = data;
134                $(
135                    let result = $type_param::process(result);
136                )*
137                result
138            }
139        }
140    };
141}
142
143/// Creates a stateless, in-place processor that can return an error.
144///
145/// This macro generates a struct that implements the `InPlaceProcessor<T, E>` trait.
146/// It processes data by mutating it directly and can fail with a specified error type.
147///
148/// # Parameters
149/// - `$struct_name`: The name for the new processor struct.
150/// - `$type`: The type of data to be processed (will be passed as `&mut`).
151/// - `$error_type`: The error type for the `Result`.
152/// - `$process_fn`: A function or closure that takes `&mut $type` and returns a `Result<(), $error_type>`.
153///
154/// # Examples
155///
156/// ```
157/// use type_flow_macros::inplace_processor;
158/// use type_flow_traits::InPlaceProcessor;
159///
160/// #[derive(Debug)]
161/// struct MyError;
162///
163/// fn increment(data: &mut i32) -> Result<(), MyError> {
164///     if *data > 100 {
165///         return Err(MyError);
166///     }
167///     *data += 1;
168///     Ok(())
169/// }
170///
171/// inplace_processor!(IncrementProcessor, i32, MyError, increment);
172///
173/// let mut value = 5;
174/// IncrementProcessor::process(&mut value).unwrap();
175/// assert_eq!(value, 6);
176/// ```
177#[macro_export]
178macro_rules! inplace_processor {
179    ($struct_name:ident, $type:ty, $error_type:ty, $process_fn:expr) => {
180        pub struct $struct_name;
181        impl InPlaceProcessor<$type, $error_type> for $struct_name {
182            fn process(data: &mut $type) -> Result<(), $error_type> {
183                ($process_fn)(data)
184            }
185        }
186    };
187}
188
189/// Creates a stateless pipeline of in-place processors.
190///
191/// This macro generates a struct that chains multiple `InPlaceProcessor` implementations.
192/// Data is mutated by each processor in the pipeline sequence. If any processor returns an error,
193/// the pipeline stops and forwards the error.
194///
195/// # Parameters
196/// - `$struct_name`: The name for the new pipeline struct.
197/// - `$type`: The type of data the pipeline will operate on.
198/// - `$error_type`: The common error type for the processors.
199/// - `$($processor: ty),+`: A comma-separated list of types that implement `InPlaceProcessor<$type, $error_type>`.
200///
201/// # Examples
202///
203/// ```
204/// use type_flow_macros::{inplace_processor, inplace_processor_pipeline};
205/// use type_flow_traits::InPlaceProcessor;
206/// #[derive(Debug)]
207/// struct MyError;
208///
209/// inplace_processor!(Add, i32, MyError, |x: &mut i32| { *x += 1; Ok(()) });
210/// inplace_processor!(Mul, i32, MyError, |x: &mut i32| { *x *= 2; Ok(()) });
211///
212/// inplace_processor_pipeline!(MyInPlacePipeline, i32, MyError, Add, Mul);
213///
214/// let mut value = 10;
215/// MyInPlacePipeline::process(&mut value).unwrap();
216/// assert_eq!(value, 22); // (10 + 1) * 2
217/// ```
218#[macro_export]
219macro_rules! inplace_processor_pipeline {
220    ($struct_name:ident, $type:ty, $error_type:ty, $($processor:ty),+) => {
221        pub struct $struct_name;
222        impl InPlaceProcessor<$type, $error_type> for $struct_name {
223            fn process(data: &mut $type) -> Result<(), $error_type> {
224                $(
225                    <$processor>::process(data)?;
226                )*
227                Ok(())
228            }
229        }
230    }
231}
232/// Creates a generic, stateless, in-place processor pipeline.
233///
234/// This macro generates a struct that is generic over its `InPlaceProcessor`s.
235/// This allows for creating flexible in-place pipelines where the exact processors can
236/// be specified later.
237///
238/// # Parameters
239/// - `$struct_name`: The name for the new generic pipeline struct.
240/// - `$processor_type`: The data type the pipeline operates on.
241/// - `$processor_error_type`: The common error type.
242/// - `$($type_param:ident),+`: A comma-separated list of generic type parameter identifiers,
243///   each constrained to implement `InPlaceProcessor`.
244///
245/// # Examples
246///
247/// ```
248/// use type_flow_macros::{inplace_processor, type_flow_inplace_processor_pipeline};
249/// use type_flow_traits::InPlaceProcessor;
250/// #[derive(Debug)]
251/// struct MyError;
252///
253/// inplace_processor!(AddTen, i32, MyError, |x: &mut i32| { *x += 10; Ok(()) });
254/// inplace_processor!(DivTwo, i32, MyError, |x: &mut i32| { *x /= 2; Ok(()) });
255///
256/// type_flow_inplace_processor_pipeline!(GenericInPlacePipeline, i32, MyError, P1, P2);
257///
258/// let mut value = 20;
259/// GenericInPlacePipeline::<AddTen, DivTwo>::process(&mut value).unwrap();
260/// assert_eq!(value, 15); // (20 + 10) / 2
261/// ```
262#[macro_export]
263macro_rules! type_flow_inplace_processor_pipeline {
264    ($struct_name:ident, $processor_type:ty, $processor_error_type:ty, $($type_param:ident),+) => {
265        pub struct $struct_name<$($type_param: InPlaceProcessor<$processor_type, $processor_error_type>),*> {
266            _marker: std::marker::PhantomData<($($type_param),*)>,
267        }
268        impl<$($type_param: InPlaceProcessor<$processor_type, $processor_error_type>),*> InPlaceProcessor<$processor_type, $processor_error_type> for $struct_name<$($type_param),*> {
269            fn process(data: &mut $processor_type) -> Result<(), $processor_error_type> {
270                $(
271                    $type_param::process(data)?;
272                )*
273                Ok(())
274            }
275        }
276    };
277}
278
279/// Creates a stateless processor that transforms data from an input type to an output type.
280///
281/// This macro generates a struct implementing the `TransformProcessor<I, O>` trait.
282///
283/// # Parameters
284/// - `$struct_name`: The name for the new processor struct.
285/// - `$input_type`: The type of the input data.
286/// - `$output_type`: The type of the output data.
287/// - `$process_fn`: A function or closure that takes `$input_type` and returns `$output_type`.
288///
289/// # Examples
290///
291/// ```
292/// use type_flow_macros::{transform_processor};
293/// use type_flow_traits::TransformProcessor;
294///
295/// // This processor transforms an i32 to a String.
296/// transform_processor!(IntToString, i32, String, |x: i32| x.to_string());
297///
298/// let result = IntToString::process(123);
299/// assert_eq!(result, "123");
300/// ```
301#[macro_export]
302macro_rules! transform_processor {
303    ($struct_name:ident, $input_type:ty, $output_type:ty, $process_fn:expr) => {
304        pub struct $struct_name;
305        impl TransformProcessor<$input_type, $output_type> for $struct_name {
306            fn process(data: $input_type) -> $output_type {
307                ($process_fn)(data)
308            }
309        }
310    };
311}
312
313/// Creates a stateful processor that maintains its own internal state.
314///
315/// This macro generates a struct that implements `StatefulProcessor<T>`. The processing logic
316/// can read and modify the internal state during its operation.
317///
318/// Two variants are available:
319/// 1. Takes a state type and requires the state to be provided via a `new()` constructor.
320/// 2. Takes a state type and an initial value expression, providing a `new()` constructor with no arguments.
321///
322/// # Arms
323///
324/// ## 1. With `new(state)` constructor
325/// - `$struct_name`: Name of the processor struct.
326/// - `$state_type`: Type of the internal state.
327/// - `$type`: Type of the data to be processed.
328/// - `$process_fn`: A closure `|state, data| -> new_data`.
329///
330/// ## 2. With `new()` constructor and initial state
331/// - `$struct_name`: Name of the processor struct.
332/// - `$state_type`: Type of the internal state.
333/// - `$state_value`: An expression that evaluates to the initial state.
334/// - `$type`: Type of the data to be processed.
335/// - `$process_fn`: A closure `|state, data| -> new_data`.
336///
337/// # Examples
338///
339/// ### 1. With `new(state)`
340/// ```
341/// use type_flow_macros::stateful_processor;
342/// use type_flow_traits::StatefulProcessor;
343///
344/// // A processor that adds a configurable number to the input.
345/// stateful_processor!(AddN, i32, i32, |state: &mut i32, data: i32| {
346///     data + *state
347/// });
348///
349/// let mut processor = AddN::new(5); // State is 5
350/// assert_eq!(processor.process(10), 15);
351/// assert_eq!(processor.process(20), 25); // State remains 5
352/// ```
353///
354/// ### 2. With initial state value
355/// ```
356/// use type_flow_macros::stateful_processor;
357/// use type_flow_traits::StatefulProcessor;
358/// // A processor that accumulates values.
359/// stateful_processor!(Accumulator, i32, 0, i32, |state: &mut i32, data: i32| {
360///     *state += data;
361///     *state // returns the new accumulated value
362/// });
363///
364/// let mut processor = Accumulator::new();
365/// assert_eq!(processor.process(5), 5);
366/// assert_eq!(processor.process(10), 15);
367/// assert_eq!(processor.process(-3), 12);
368/// ```
369#[macro_export]
370macro_rules! stateful_processor {
371    // Original version with constructor
372    ($struct_name:ident, $state_type:ty, $type:ty, $process_fn:expr) => {
373        pub struct $struct_name {
374            state: $state_type
375        }
376        impl $struct_name {
377            pub fn new(state: $state_type) -> Self {
378                Self {
379                    state
380                }
381            }
382        }
383
384        impl StatefulProcessor<$type> for $struct_name {
385            fn process(&mut self, data: $type) -> $type {
386                let state = &mut self.state;
387                ($process_fn)(state, data)
388            }
389        }
390    };
391
392    // Version with direct state value
393    ($struct_name:ident, $state_type:ty, $state_value:expr, $type:ty, $process_fn:expr) => {
394        pub struct $struct_name {
395            state: $state_type
396        }
397
398        impl $struct_name {
399            pub fn new() -> Self {
400                Self {
401                    state: $state_value
402                }
403            }
404            pub fn instance() -> Self {
405                Self::new()
406            }
407        }
408        impl StatefulProcessor<$type> for $struct_name {
409            fn process(&mut self, data: $type) -> $type {
410                let state = &mut self.state;
411                ($process_fn)(state, data)
412            }
413        }
414    };
415}
416
417/// Creates a pipeline of stateful processors.
418///
419/// This macro generates a struct that holds multiple stateful processors and
420/// processes data through them in sequence. Each processor in the pipeline
421/// maintains its own state.
422///
423/// # Arms
424///
425/// ## 1. With named fields for processors
426/// - `$pipeline_name`: Name for the pipeline struct.
427/// - `$data_type`: The type of data the pipeline operates on.
428/// - `$($processor_field:ident: $processor_type:ty),+`: A comma-separated list of `field: Type` pairs for the processors.
429///
430/// ## 2. With auto-generated fields (delegates to a proc-macro)
431/// - `$pipeline_name`: Name for the pipeline struct.
432/// - `$data_type`: The type of data the pipeline operates on.
433/// - `$($processor_type:ty),+`: A comma-separated list of processor types.
434///
435/// # Examples
436///
437/// ```
438/// use type_flow_macros::{stateful_processor, stateful_processor_pipeline};
439/// use type_flow_traits::StatefulProcessor;
440///
441/// // A processor that adds its call count to the data
442/// stateful_processor!(CallCountAdder, i32, 0, i32, |state: &mut i32, data: i32| {
443///     *state += 1;
444///     data + *state
445/// });
446///
447/// // A processor that multiplies data by its call count
448/// stateful_processor!(CallCountMultiplier, i32, 0, i32, |state: &mut i32, data: i32| {
449///     *state += 1;
450///     data * *state
451/// });
452///
453/// // Arm 1: Named fields
454/// stateful_processor_pipeline!(MyStatefulPipeline, i32, adder: CallCountAdder, multiplier: CallCountMultiplier);
455///
456/// let mut pipeline = MyStatefulPipeline::new(CallCountAdder::new(), CallCountMultiplier::new());
457/// // First run: process(10) -> adder(state=1) -> 11 -> multiplier(state=1) -> 11
458/// assert_eq!(pipeline.process(10), 11);
459/// // Second run: process(10) -> adder(state=2) -> 12 -> multiplier(state=2) -> 24
460/// assert_eq!(pipeline.process(10), 24);
461///
462/// // Arm 2: Auto-generated fields
463/// stateful_processor_pipeline!(MyAnonPipeline, i32, CallCountMultiplier, CallCountAdder);
464/// let mut anon_pipeline = MyAnonPipeline::new(CallCountMultiplier::new(), CallCountAdder::new());
465/// assert_eq!(anon_pipeline.process(5), 6); // (5+1)*1
466/// assert_eq!(anon_pipeline.process(5), 12); // (5+2)*2
467/// ```
468#[macro_export]
469macro_rules! stateful_processor_pipeline {
470    ($pipeline_name:ident, $data_type:ty, $($processor_field:ident: $processor_type:ty),+) => {
471        pub struct $pipeline_name {
472            $(
473                $processor_field: $processor_type,
474            )+
475        }
476
477        impl $pipeline_name {
478            pub fn new($($processor_field: $processor_type),+) -> Self {
479                Self {
480                    $(
481                        $processor_field,
482                    )+
483                }
484            }
485        }
486
487        impl StatefulProcessor<$data_type> for $pipeline_name {
488            fn process(&mut self, mut data: $data_type) -> $data_type {
489                $(
490                    data = self.$processor_field.process(data);
491                )*
492                data
493            }
494        }
495    };
496    
497    ($pipeline_name:ident, $data_type:ty, $($processor_type:ty),+) => {
498        type_flow_proc_macros::stateful_processor_pipeline_with_index!($pipeline_name, $data_type, $($processor_type),+);
499    };
500}
501
502/// Creates a stateful, in-place processor that can return an error.
503///
504/// This macro generates a struct that implements `InPlaceStatefulProcessor<T, E>`,
505/// combining state management with in-place mutation and error handling.
506///
507/// # Arms
508///
509/// ## 1. With `new(state)` constructor
510/// - `$struct_name`: Name of the processor struct.
511/// - `$state_type`: Type of the internal state.
512/// - `$type`: Type of data to process.
513/// - `$error_type`: Error type for the `Result`.
514/// - `$process_fn`: A closure `|state, data| -> Result<(), E>`.
515///
516/// ## 2. With `new()` constructor and initial state
517/// - `$struct_name`: Name of the processor struct.
518/// - `$state_type`: Type of the internal state.
519/// - `$state_value`: An expression for the initial state.
520/// - `$type`: Type of data to process.
521/// - `$error_type`: Error type for the `Result`.
522/// - `$process_fn`: A closure `|state, data| -> Result<(), E>`.
523///
524/// # Examples
525///
526/// ### 1. With `new(state)`
527/// ```
528/// use type_flow_macros::inplace_stateful_processor;
529/// use type_flow_traits::InPlaceStatefulProcessor;
530/// #[derive(Debug)]
531/// struct MyError;
532///
533/// // Adds a configured value, fails if result exceeds a limit from state.
534/// inplace_stateful_processor!(AddNLimited, (i32, i32), i32, MyError, |state: &mut (i32, i32), data: &mut i32| {
535///     *data += state.0;
536///     if *data > state.1 { Err(MyError) } else { Ok(()) }
537/// });
538///
539/// let mut processor = AddNLimited::new((5, 100)); // Add 5, limit 100
540/// let mut value = 10;
541/// processor.process(&mut value).unwrap();
542/// assert_eq!(value, 15);
543/// ```
544///
545/// ### 2. With initial state
546/// ```
547/// use type_flow_macros::inplace_stateful_processor;
548/// use type_flow_traits::InPlaceStatefulProcessor;
549///
550/// // Accumulates values in-place.
551/// inplace_stateful_processor!(Accumulator, i32, 0, i32, (), |state: &mut i32, data: &mut i32| {
552///     *state += *data;
553///     *data = *state;
554///     Ok(())
555/// });
556///
557/// let mut processor = Accumulator::new();
558/// let (mut val1, mut val2) = (5, 10);
559/// processor.process(&mut val1).unwrap();
560/// assert_eq!(val1, 5);
561/// processor.process(&mut val2).unwrap();
562/// assert_eq!(val2, 15); // 5 (previous state) + 10
563/// ```
564#[macro_export]
565macro_rules! inplace_stateful_processor {
566    ($struct_name:ident, $state_type:ty, $type:ty, $error_type:ty, $process_fn:expr) => {
567        pub struct $struct_name {
568            state: $state_type
569        }
570        impl $struct_name {
571            pub fn new(state: $state_type) -> Self {
572                Self {
573                    state
574                }
575            }
576        }
577        impl InPlaceStatefulProcessor<$type, $error_type> for $struct_name {
578            fn process(&mut self, data: &mut $type) -> Result<(), $error_type> {
579                let state = &mut self.state;
580                ($process_fn)(state, data)
581            }
582        }
583    };
584    ($struct_name:ident, $state_type:ty, $state_value:expr, $type:ty, $error_type:ty, $process_fn:expr) => {
585        pub struct $struct_name {
586            state: $state_type
587        }
588        impl $struct_name {
589            pub fn new() -> Self {
590                Self {
591                    state: $state_value
592                }
593            }
594            pub fn instance() -> Self {
595                Self::new()
596            }
597        }
598        impl InPlaceStatefulProcessor<$type, $error_type> for $struct_name {
599            fn process(&mut self, data: &mut $type) -> Result<(), $error_type> {
600                let state = &mut self.state;
601                ($process_fn)(state, data)
602            }
603        }
604    };
605}
606
607/// Creates a pipeline of stateful, in-place processors.
608///
609/// Generates a struct that holds multiple `InPlaceStatefulProcessor`s and
610/// processes data through them sequentially. Each processor can mutate the data
611/// and its own state. The pipeline stops if any processor returns an error.
612///
613/// # Arms
614///
615/// ## 1. With named fields
616/// - `$pipeline_name`: Name for the pipeline struct.
617/// - `$data_type`: The type of data for the pipeline.
618/// - `$error_type`: The common error type.
619/// - `$($processor_field:ident: $processor_type:ty),+`: A list of `field: Type` pairs.
620///
621/// ## 2. With auto-generated fields (delegates to a proc-macro)
622/// - `$pipeline_name`: Name for the pipeline struct.
623/// - `$data_type`: The type of data for the pipeline.
624/// - `$error_type`: The common error type.
625/// - `$($processor_type:ty),+`: A list of processor types.
626///
627/// # Examples
628///
629/// ```
630/// use type_flow_macros::{inplace_stateful_processor, inplace_stateful_processor_pipeline};
631/// use type_flow_traits::InPlaceStatefulProcessor;
632/// use type_flow_proc_macros::inplace_stateful_processor_pipeline_with_index;
633/// #[derive(Debug)]
634/// struct MyError;
635///
636/// // Processor that adds its call count to data.
637/// inplace_stateful_processor!(CounterAdd, i32, 0, i32, MyError, |state: &mut i32, data: &mut i32| {
638///     *state += 1;
639///     *data += *state;
640///     Ok(())
641/// });
642///
643/// // Processor that multiplies data by its call count.
644/// inplace_stateful_processor!(CounterMul, i32, 0, i32, MyError, |state: &mut i32, data: &mut i32| {
645///     *state += 1;
646///     *data *= *state;
647///     Ok(())
648/// });
649///
650/// // Arm 1: Named fields
651/// inplace_stateful_processor_pipeline!(MyPipeline, i32, MyError, adder: CounterAdd, multiplier: CounterMul);
652///
653/// let mut pipeline = MyPipeline::new(CounterAdd::new(), CounterMul::new());
654/// let mut value = 10;
655///
656/// // First run: value=10 -> adder(s=1) -> 11 -> multiplier(s=1) -> 11
657/// pipeline.process(&mut value).unwrap();
658/// assert_eq!(value, 11);
659///
660/// // Second run: value=11 -> adder(s=2) -> 13 -> multiplier(s=2) -> 26
661/// pipeline.process(&mut value).unwrap();
662/// assert_eq!(value, 26);
663/// ```
664#[macro_export]
665macro_rules! inplace_stateful_processor_pipeline {
666    ($pipeline_name:ident, $data_type:ty, $error_type:ty, $($processor_field:ident: $processor_type:ty),+) => {
667        pub struct $pipeline_name {
668            $(
669                $processor_field: $processor_type,
670            )+
671        }
672        impl $pipeline_name {
673            pub fn new($($processor_field: $processor_type),+) -> Self {
674                Self {
675                    $(
676                        $processor_field,
677                    )+
678                }
679            }
680        }
681        impl InPlaceStatefulProcessor<$data_type, $error_type> for $pipeline_name {
682            fn process(&mut self, data: &mut $data_type) -> Result<(), $error_type> {
683                $(
684                    self.$processor_field.process(data)?;
685                )*
686                Ok(())
687            }
688        }
689    };
690    ($pipeline_name:ident, $data_type:ty, $error_type:ty, $($processor_type:ty),+) => {
691        type_flow_proc_macros::inplace_stateful_processor_pipeline_with_index!($pipeline_name, $data_type, $error_type, $($processor_type),+);
692    };
693}
694
695/// Creates a generic, stateful, in-place processor pipeline with type-level permutation capabilities.
696///
697/// This powerful macro generates a pipeline struct that is generic over its
698/// `InPlaceStatefulProcessor`s. It automatically implements traits that allow the
699/// order of processors to be rearranged at compile time through type manipulation.
700///
701/// # Supported Operations
702///
703/// The generated pipeline supports the following type-level transformations through trait implementations:
704///
705/// - `Reverse`: Reverses the order of processors in the pipeline
706/// - `ShiftLeft`: Rotates all processors one position left
707/// - `ShiftRight`: Rotates all processors one position right 
708/// - `SwapStartEnd`: Exchanges the first and last processors
709/// - `SwapArbitraryProcessors<I, J>`: Swaps processors at any two positions
710///
711/// # Macro Parameters
712///
713/// ## Variant 1: With named fields
714/// - `$struct_name`: Name for the generated pipeline struct
715/// - `$processor_type`: Type of data flowing through the pipeline
716/// - `$processor_error_type`: Common error type used by all processors
717/// - `$($field_name:ident : $type_param:ident),+`: Field names and corresponding generic type parameters
718///
719/// ## Variant 2: With processor count
720/// - `$struct_name`: Name for the generated pipeline struct
721/// - `$processor_type`: Type of data flowing through the pipeline
722/// - `$processor_error_type`: Common error type used by all processors
723/// - `$number_of_processors`: A literal integer specifying how many processors the pipeline should support
724///
725/// # Examples
726///
727/// ```
728/// use type_flow_macros::{
729///     type_flow_inplace_stateful_processor_pipeline,
730///     inplace_stateful_processor
731/// };
732/// use type_flow_proc_macros::implement_processor_swapping;
733/// use type_flow_traits::{InPlaceStatefulProcessor,
734///     Reverse, ShiftLeft};
735/// #[derive(Debug)]
736/// struct MyError;
737///
738/// // These processors have a state type of `()` and don't use it.
739/// inplace_stateful_processor!(AddOne, (), i32, MyError, |_, d: &mut i32| { *d += 1; Ok(()) });
740/// inplace_stateful_processor!(MulTwo, (), i32, MyError, |_, d: &mut i32| { *d *= 2; Ok(()) });
741/// inplace_stateful_processor!(SubThree, (), i32, MyError, |_, d: &mut i32| { *d -= 3; Ok(()) });
742///
743/// // Using the variant of the macro that creates field names from type names.
744/// type_flow_inplace_stateful_processor_pipeline!(
745///     MyPipeline, i32, MyError, a: A, b: B, c: C
746/// );
747///
748/// // Original pipeline
749/// let mut pipeline = MyPipeline::new(AddOne::new(()), MulTwo::new(()), SubThree::new(()));
750/// let mut value = 10;
751/// pipeline.process(&mut value).unwrap();
752/// assert_eq!(value, 19); // (10 + 1) * 2 - 3 = 19
753///
754/// // Reversed pipeline. Note: .reverse() consumes the pipeline and returns a new type.
755/// let mut reversed_pipeline = MyPipeline::new(AddOne::new(()), MulTwo::new(()), SubThree::new(()))
756///     .reverse();
757/// let mut value_rev = 10;
758/// reversed_pipeline.process(&mut value_rev).unwrap();
759/// assert_eq!(value_rev, 15); // (10 - 3) * 2 + 1 = 15
760///
761/// // Shifted pipeline
762/// let mut shifted_pipeline = MyPipeline::new(AddOne::new(()), MulTwo::new(()), SubThree::new(()))
763///     .shift_left();
764/// let mut value_shift = 10;
765/// shifted_pipeline.process(&mut value_shift).unwrap();
766/// assert_eq!(value_shift, 18); // (10 * 2 - 3) + 1 = 18
767/// ```
768#[macro_export]
769macro_rules! type_flow_inplace_stateful_processor_pipeline {
770    ($struct_name:ident, $processor_type:ty, $processor_error_type:ty, $($field_name:ident : $type_param:ident),+) => {
771        #[implement_processor_swapping] 
772        pub struct $struct_name<$($type_param: InPlaceStatefulProcessor<$processor_type, $processor_error_type>),*> {
773            _marker: std::marker::PhantomData<($($type_param),*)>,
774            $(
775                $field_name: $type_param,
776            )+
777        }
778        impl<$($type_param: InPlaceStatefulProcessor<$processor_type, $processor_error_type>),*> $struct_name<$($type_param),*> {
779            pub fn new($($field_name: $type_param),+) -> Self {
780                Self {
781                    _marker: std::marker::PhantomData,
782                    $(
783                        $field_name,
784                    )+
785                }
786            }
787        }
788        impl<$($type_param: InPlaceStatefulProcessor<$processor_type, $processor_error_type>),*> InPlaceStatefulProcessor<$processor_type, $processor_error_type> for $struct_name<$($type_param),*> {
789            fn process(&mut self, data: &mut $processor_type) -> Result<(), $processor_error_type> {
790                $(
791                    self.$field_name.process(data)?;
792                )*
793                Ok(())
794            }
795        }
796    };
797    ($struct_name:ident, $processor_type:ty, $processor_error_type:ty, $number_of_processors:literal) => {
798        type_flow_proc_macros::type_flow_inplace_stateful_processor_pipeline_by_count!($struct_name, $processor_type, $processor_error_type, $number_of_processors);
799    };
800}