type_flow_macros/
lib.rs

1#[allow(unused_imports)]
2use type_flow_traits::{
3    Processor,
4    InPlaceProcessor,
5    TransformProcessor,
6    StatefulProcessor,
7    InPlaceStatefulProcessor,
8};
9/*macro_rules! count_tts {
10    () => { 0 };
11    ($odd:tt $($a:tt $b:tt)*) => { (count_tts!($($a)*) << 1) | 1 };
12    ($($a:tt $even:tt)*) => { count_tts!($($a)*) << 1 };
13}*/
14
15#[macro_export]
16macro_rules! processor {
17    ($struct_name:ident, $type:ty, $process_fn:expr) => {
18        pub struct $struct_name;
19        impl Processor<$type> for $struct_name {
20            fn process(data: $type) -> $type {
21                ($process_fn)(data)
22            }
23        }
24    };
25}
26
27#[macro_export]
28macro_rules! processor_pipeline {
29    ($struct_name:ident, $type:ty, $($processor:ty),+) => {
30        pub struct $struct_name;
31        impl Processor<$type> for $struct_name {
32            fn process(data: $type) -> $type {
33                let result = data;
34                $(
35                    let result = <$processor>::process(result);
36                )*
37                result
38            }
39        }
40    }
41}
42
43#[macro_export]
44macro_rules! type_flow_processor_pipeline {
45    ($struct_name:ident, $processor_type:ty, $($type_param:ident),+) => {
46        pub struct $struct_name<$($type_param: Processor<$processor_type>),*> {
47            _marker: std::marker::PhantomData<($($type_param),*)>,
48        }
49        impl<$($type_param: Processor<$processor_type>),*> Processor<$processor_type> for $struct_name<$($type_param),*> {
50            fn process(data: $processor_type) -> $processor_type{
51                let result = data;
52                $(
53                    let result = $type_param::process(result);
54                )*
55                result
56            }
57        }
58    };
59}
60
61#[macro_export]
62macro_rules! inplace_processor {
63    ($struct_name:ident, $type:ty, $error_type:ty, $process_fn:expr) => {
64        pub struct $struct_name;
65        impl InPlaceProcessor<$type, $error_type> for $struct_name {
66            fn process(data: &mut $type) -> Result<(), $error_type> {
67                ($process_fn)(data)
68            }
69        }
70    };
71}
72
73#[macro_export]
74macro_rules! inplace_processor_pipeline {
75    ($struct_name:ident, $type:ty, $error_type:ty, $($processor:ty),+) => {
76        pub struct $struct_name;
77        impl InPlaceProcessor<$type, $error_type> for $struct_name {
78            fn process(data: &mut $type) -> Result<(), $error_type> {
79                $(
80                    <$processor>::process(data)?;
81                )*
82                Ok(())
83            }
84        }
85    }
86}
87#[macro_export]
88macro_rules! type_flow_inplace_processor_pipeline {
89    ($struct_name:ident, $processor_type:ty, $processor_error_type:ty, $($type_param:ident),+) => {
90        pub struct $struct_name<$($type_param: InPlaceProcessor<$processor_type, $processor_error_type>),*> {
91            _marker: std::marker::PhantomData<($($type_param),*)>,
92        }
93        impl<$($type_param: InPlaceProcessor<$processor_type, $processor_error_type>),*> InPlaceProcessor<$processor_type, $processor_error_type> for $struct_name<$($type_param),*> {
94            fn process(data: &mut $processor_type) -> Result<(), $processor_error_type> {
95                $(
96                    $type_param::process(data)?;
97                )*
98                Ok(())
99            }
100        }
101    };
102}
103
104#[macro_export]
105macro_rules! transform_processor {
106    ($struct_name:ident, $input_type:ty, $output_type:ty, $process_fn:expr) => {
107        pub struct $struct_name;
108        impl TransformProcessor<$input_type, $output_type> for $struct_name {
109            fn process(data: $input_type) -> $output_type {
110                ($process_fn)(data)
111            }
112        }
113    };
114}
115
116#[macro_export]
117macro_rules! stateful_processor {
118    // Original version with constructor
119    ($struct_name:ident, $state_type:ty, $type:ty, $process_fn:expr) => {
120        pub struct $struct_name {
121            state: $state_type
122        }
123        impl $struct_name {
124            pub fn new(state: $state_type) -> Self {
125                Self {
126                    state
127                }
128            }
129        }
130
131        impl StatefulProcessor<$type> for $struct_name {
132            fn process(&mut self, data: $type) -> $type {
133                let state = &mut self.state;
134                ($process_fn)(state, data)
135            }
136        }
137    };
138
139    // Version with direct state value
140    ($struct_name:ident, $state_type:ty, $state_value:expr, $type:ty, $process_fn:expr) => {
141        pub struct $struct_name {
142            state: $state_type
143        }
144
145        impl $struct_name {
146            pub fn new() -> Self {
147                Self {
148                    state: $state_value
149                }
150            }
151            pub fn instance() -> Self {
152                Self::new()
153            }
154        }
155        impl StatefulProcessor<$type> for $struct_name {
156            fn process(&mut self, data: $type) -> $type {
157                let state = &mut self.state;
158                ($process_fn)(state, data)
159            }
160        }
161    };
162}
163
164#[macro_export]
165macro_rules! stateful_processor_pipeline {
166    ($pipeline_name:ident, $data_type:ty, $($processor_field:ident: $processor_type:ty),+) => {
167        pub struct $pipeline_name {
168            $(
169                $processor_field: $processor_type,
170            )+
171        }
172
173        impl $pipeline_name {
174            pub fn new($($processor_field: $processor_type),+) -> Self {
175                Self {
176                    $(
177                        $processor_field,
178                    )+
179                }
180            }
181        }
182
183        impl StatefulProcessor<$data_type> for $pipeline_name {
184            fn process(&mut self, mut data: $data_type) -> $data_type {
185                $(
186                    data = self.$processor_field.process(data);
187                )*
188                data
189            }
190        }
191    };
192    
193    ($pipeline_name:ident, $data_type:ty, $($processor_type:ty),+) => {
194        type_flow_proc_macros::stateful_processor_pipeline_with_index!($pipeline_name, $data_type, $($processor_type),+);
195    };
196}
197
198#[macro_export]
199macro_rules! inplace_stateful_processor {
200    ($struct_name:ident, $state_type:ty, $type:ty, $error_type:ty, $process_fn:expr) => {
201        pub struct $struct_name {
202            state: $state_type
203        }
204        impl $struct_name {
205            pub fn new(state: $state_type) -> Self {
206                Self {
207                    state
208                }
209            }
210        }
211        impl InPlaceStatefulProcessor<$type, $error_type> for $struct_name {
212            fn process(&mut self, data: &mut $type) -> Result<(), $error_type> {
213                let state = &mut self.state;
214                ($process_fn)(state, data)
215            }
216        }
217    };
218    ($struct_name:ident, $state_type:ty, $state_value:expr, $type:ty, $error_type:ty, $process_fn:expr) => {
219        pub struct $struct_name {
220            state: $state_type
221        }
222        impl $struct_name {
223            pub fn new() -> Self {
224                Self {
225                    state: $state_value
226                }
227            }
228            pub fn instance() -> Self {
229                Self::new()
230            }
231        }
232        impl InPlaceStatefulProcessor<$type, $error_type> for $struct_name {
233            fn process(&mut self, data: &mut $type) -> Result<(), $error_type> {
234                let state = &mut self.state;
235                ($process_fn)(state, data)
236            }
237        }
238    };
239}
240
241#[macro_export]
242macro_rules! inplace_stateful_processor_pipeline {
243    ($pipeline_name:ident, $data_type:ty, $error_type:ty, $($processor_field:ident: $processor_type:ty),+) => {
244        pub struct $pipeline_name {
245            $(
246                $processor_field: $processor_type,
247            )+
248        }
249        impl $pipeline_name {
250            pub fn new($($processor_field: $processor_type),+) -> Self {
251                Self {
252                    $(
253                        $processor_field,
254                    )+
255                }
256            }
257        }
258        impl InPlaceStatefulProcessor<$data_type, $error_type> for $pipeline_name {
259            fn process(&mut self, data: &mut $data_type) -> Result<(), $error_type> {
260                $(
261                    self.$processor_field.process(data)?;
262                )*
263                Ok(())
264            }
265        }
266    };
267    ($pipeline_name:ident, $data_type:ty, $error_type:ty, $($processor_type:ty),+) => {
268        type_flow_proc_macros::inplace_stateful_processor_pipeline_with_index!($pipeline_name, $data_type, $error_type, $($processor_type),+);
269    };
270}
271
272#[macro_export]
273macro_rules! impl_shift_left {
274    // Case for a single type parameter / field
275    ($struct_name:ident, ($type_param:ident), ($field_name:ident), $processor_common_type:ty, $processor_error_type:ty) => {
276        impl<$type_param: InPlaceStatefulProcessor<$processor_common_type, $processor_error_type>> type_flow_traits::ShiftLeft for $struct_name<$type_param> {
277            type Output = $struct_name<$type_param>;
278            fn shift_left(self) -> Self::Output {
279                Self::Output {
280                    _marker: std::marker::PhantomData,
281                    $field_name: self.$field_name
282                }
283            }
284        }
285    };
286    // Case 2: Multiple elements (at least two) - Entry point for recursion
287    // This arm matches when there's a first type/field and at least one more type/field in $rest_t/$rest_f.
288    ($struct_name:ident, ($first_t:ident, $($rest_t:ident),+), ($first_f:ident, $($rest_f:ident),+), $proc_ty:ty, $proc_err_ty:ty) => {
289        impl_shift_left!(@internal_shift_left
290            $struct_name; $proc_ty; $proc_err_ty;  // Fixed parameters passed along
291            $first_t; $first_f;                    // Original first type ($orig_first_t) and field ($orig_first_f)
292            // Lists of remaining types and fields to process to find middle and last elements:
293            @process_types $($rest_t),+; @process_fields $($rest_f),+;
294            // Accumulators for middle types and fields, initially empty:
295            @middle_types ; @middle_fields ;
296        );
297    };
298    // Internal rule: Recursive step
299    // This rule is matched when there are two or more elements remaining in the @process_types/@process_fields lists.
300    // It takes the 'current' element, adds it to the 'middle' accumulator, and recurses on the 'tail'.
301    (@internal_shift_left
302        $struct_name:ident; $proc_ty:ty; $proc_err_ty:ty; // Fixed parameters
303        $orig_first_t:ident; $orig_first_f:ident;         // Original first type and field
304        // Types/fields to process: current one, followed by one or more in the tail
305        @process_types $current_t:ident, $($tail_t:ident),+; @process_fields $current_f:ident, $($tail_f:ident),+;
306        @middle_types $($middle_t_acc:ident),*; @middle_fields $($middle_f_acc:ident),*; // Accumulated middle types/fields so far
307    ) => {
308        impl_shift_left!(@internal_shift_left
309            $struct_name; $proc_ty; $proc_err_ty;
310            $orig_first_t; $orig_first_f;
311            // Continue processing with the tail of the lists:
312            @process_types $($tail_t),+; @process_fields $($tail_f),+;
313            // Add the 'current' type and field to their respective accumulators for middle elements:
314            @middle_types $($middle_t_acc,)* $current_t;
315            @middle_fields $($middle_f_acc,)* $current_f;
316        );
317    };
318    // Internal rule: Base case for recursion
319    // This rule is matched when exactly one element remains in the @process_types/@process_fields lists.
320    // This single remaining element is the 'last' element of the original list.
321    (@internal_shift_left
322        $struct_name:ident; $proc_ty:ty; $proc_err_ty:ty; // Fixed parameters
323        $first_t:ident; $first_f:ident;                   // Original first type ($orig_first_t) and field ($orig_first_f)
324        // The last type and field from the original lists:
325        @process_types $last_t:ident; @process_fields $last_f:ident;
326        // All accumulated middle types and fields:
327        @middle_types $($middle_t_acc:ident),*; @middle_fields $($middle_f_acc:ident),*;
328    ) => {
329        impl_shift_left!(@internal_shift_left
330            $struct_name; $proc_ty; $proc_err_ty; // Fixed parameters
331            $first_t; $first_f;                   // Original first type ($orig_first_t) and field ($orig_first_f)
332            // The last type and field from the original lists:
333            @process_types $last_t; @process_fields $last_f;
334            // All accumulated middle types and fields:
335            @middle_types $($middle_t_acc),*; @middle_fields $($middle_f_acc),*;
336            @original_order_field_names $first_f, $($middle_f_acc,)* $last_f;
337            @new_order_field_names $($middle_f_acc,)* $last_f, $first_f;
338        );
339    };
340
341    (@internal_shift_left
342        $struct_name:ident; $proc_ty:ty; $proc_err_ty:ty;
343        $first_t:ident; $first_f:ident;  @process_types $last_t:ident; @process_fields $last_f:ident;
344        @middle_types $($middle_t_acc:ident),*; @middle_fields $($middle_f_acc:ident),*;
345        @original_order_field_names $($original_order_field_name:ident),*; @new_order_field_names $($new_order_field_name:ident),*;
346    ) => {
347        impl<
348            $first_t: InPlaceStatefulProcessor<$proc_ty, $proc_err_ty>,
349            $($middle_t_acc: InPlaceStatefulProcessor<$proc_ty, $proc_err_ty>,)*
350            $last_t: InPlaceStatefulProcessor<$proc_ty, $proc_err_ty>
351        > type_flow_traits::ShiftLeft for $struct_name<$first_t, $($middle_t_acc,)* $last_t> {
352            // The type of this struct is shifted to the left fo the original
353            type ShiftedLeft = $struct_name<$($middle_t_acc,)* $last_t, $first_t>;
354            fn shift_left(self) -> Self::ShiftedLeft {
355                Self::ShiftedLeft {
356                    _marker: std::marker::PhantomData,
357                    $($original_order_field_name: self.$new_order_field_name),*
358                }
359            }
360        }
361    };
362}
363
364#[macro_export]
365macro_rules! impl_shift_right {
366    // Case for a single type parameter / field
367    ($struct_name:ident, ($type_param:ident), ($field_name:ident), $processor_common_type:ty, $processor_error_type:ty) => {
368        impl<$type_param: InPlaceStatefulProcessor<$processor_common_type, $processor_error_type>> type_flow_traits::ShiftRight for $struct_name<$type_param> {
369            type Output = $struct_name<$type_param>;
370            fn shift_right(self) -> Self::Output {
371                Self::Output {
372                    _marker: std::marker::PhantomData,
373                    $field_name: self.$field_name
374                }
375            }
376        }
377    };
378    // Case 2: Multiple elements (at least two) - Entry point for recursion
379    // This arm matches when there's a first type/field and at least one more type/field in $rest_t/$rest_f.
380    ($struct_name:ident, ($first_t:ident, $($rest_t:ident),+), ($first_f:ident, $($rest_f:ident),+), $proc_ty:ty, $proc_err_ty:ty) => {
381        impl_shift_right!(@internal_shift_right
382            $struct_name; $proc_ty; $proc_err_ty;  // Fixed parameters passed along
383            $first_t; $first_f;                    // Original first type ($orig_first_t) and field ($orig_first_f)
384            // Lists of remaining types and fields to process to find middle and last elements:
385            @process_types $($rest_t),+; @process_fields $($rest_f),+;
386            // Accumulators for middle types and fields, initially empty:
387            @middle_types ; @middle_fields ;
388        );
389    };
390    // Internal rule: Recursive step
391    // This rule is matched when there are two or more elements remaining in the @process_types/@process_fields lists.
392    // It takes the 'current' element, adds it to the 'middle' accumulator, and recurses on the 'tail'.
393    (@internal_shift_right
394        $struct_name:ident; $proc_ty:ty; $proc_err_ty:ty; // Fixed parameters
395        $orig_first_t:ident; $orig_first_f:ident;         // Original first type and field
396        // Types/fields to process: current one, followed by one or more in the tail
397        @process_types $current_t:ident, $($tail_t:ident),+; @process_fields $current_f:ident, $($tail_f:ident),+;
398        @middle_types $($middle_t_acc:ident),*; @middle_fields $($middle_f_acc:ident),*; // Accumulated middle types/fields so far
399    ) => {
400        impl_shift_right!(@internal_shift_right
401            $struct_name; $proc_ty; $proc_err_ty;
402            $orig_first_t; $orig_first_f;
403            // Continue processing with the tail of the lists:
404            @process_types $($tail_t),+; @process_fields $($tail_f),+;
405            // Add the 'current' type and field to their respective accumulators for middle elements:
406            @middle_types $($middle_t_acc,)* $current_t;
407            @middle_fields $($middle_f_acc,)* $current_f;
408        );
409    };
410    // Internal rule: Base case for recursion
411    // This rule is matched when exactly one element remains in the @process_types/@process_fields lists.
412    // This single remaining element is the 'last' element of the original list.
413    (@internal_shift_right
414        $struct_name:ident; $proc_ty:ty; $proc_err_ty:ty; // Fixed parameters
415        $first_t:ident; $first_f:ident;                   // Original first type ($orig_first_t) and field ($orig_first_f)
416        // The last type and field from the original lists:
417        @process_types $last_t:ident; @process_fields $last_f:ident;
418        // All accumulated middle types and fields:
419        @middle_types $($middle_t_acc:ident),*; @middle_fields $($middle_f_acc:ident),*;
420    ) => {
421        // Generate the trait implementation
422        // The generic parameters for the struct are: original first, all middles, original last
423        impl_shift_right!(@internal_shift_right
424            $struct_name; $proc_ty; $proc_err_ty; // Fixed parameters
425            $first_t; $first_f;                   // Original first type ($orig_first_t) and field ($orig_first_f)
426            // The last type and field from the original lists:
427            @process_types $last_t; @process_fields $last_f;
428            // All accumulated middle types and fields:
429            @middle_types $($middle_t_acc),*; @middle_fields $($middle_f_acc),*;
430            @original_order_field_names $first_f, $($middle_f_acc,)* $last_f;
431            @new_order_field_names $last_f, $first_f, $($middle_f_acc),*;
432        );
433    };
434    (@internal_shift_right
435        $struct_name:ident; $proc_ty:ty; $proc_err_ty:ty;
436        $first_t:ident; $first_f:ident;  @process_types $last_t:ident; @process_fields $last_f:ident;
437        @middle_types $($middle_t_acc:ident),*; @middle_fields $($middle_f_acc:ident),*;
438        @original_order_field_names $($original_order_field_name:ident),*; @new_order_field_names $($new_order_field_name:ident),*;
439    ) => {
440        impl<
441            $first_t: InPlaceStatefulProcessor<$proc_ty, $proc_err_ty>,
442            $($middle_t_acc: InPlaceStatefulProcessor<$proc_ty, $proc_err_ty>,)*
443            $last_t: InPlaceStatefulProcessor<$proc_ty, $proc_err_ty>
444        > type_flow_traits::ShiftRight for $struct_name<$first_t, $($middle_t_acc,)* $last_t> {
445            // The type of this struct is shifted to the left fo the original
446            type ShiftedRight = $struct_name<$last_t, $first_t, $($middle_t_acc),*>;
447            fn shift_right(self) -> Self::ShiftedRight {
448                Self::ShiftedRight {
449                    _marker: std::marker::PhantomData,
450                    $($original_order_field_name: self.$new_order_field_name),*
451                }
452            }
453        }
454    };
455}
456
457#[macro_export]
458macro_rules! impl_swap_start_end {
459    // Case 1: Single element (no change needed for swap)
460    ($struct_name:ident, ($type_p:ident), ($field_n:ident), $processor_common_type:ty, $processor_error_type:ty) => {
461        impl<$type_p: InPlaceStatefulProcessor<$processor_common_type, $processor_error_type>> type_flow_traits::SwapStartEnd for $struct_name<$type_p> {
462            type Output = $struct_name<$type_p>;
463            fn swap(self) -> Self::Output {
464                Self::Output { _marker: std::marker::PhantomData, $field_n: self.$field_n }
465            }
466        }
467    };
468
469    // Case 2: Multiple elements (at least two) - Entry point for recursion
470    // This arm matches when there's a first type/field and at least one more type/field in $rest_t/$rest_f.
471    ($struct_name:ident, ($first_t:ident, $($rest_t:ident),+), ($first_f:ident, $($rest_f:ident),+), $proc_ty:ty, $proc_err_ty:ty) => {
472        impl_swap_start_end!(@internal_swap
473            $struct_name; $proc_ty; $proc_err_ty; // Fixed parameters passed along
474            $first_t; $first_f;                  // The very first type and field from the original list
475            // Lists of remaining types and fields to process to find middle and last elements:
476            @process_types $($rest_t),+; @process_fields $($rest_f),+;
477            // Accumulators for middle types and fields, initially empty:
478            @middle_types ; @middle_fields ;
479        );
480    };
481
482    // Internal rule: Recursive step
483    // This rule is matched when there are two or more elements remaining in the @process_types/@process_fields lists.
484    // It takes the 'current' element, adds it to the 'middle' accumulator, and recurses on the 'tail'.
485    (@internal_swap
486        $struct_name:ident; $proc_ty:ty; $proc_err_ty:ty; // Fixed parameters
487        $orig_first_t:ident; $orig_first_f:ident;        // Original first type and field
488        // Types/fields to process: current one, followed by one or more in the tail
489        @process_types $current_t:ident, $($tail_t:ident),+; @process_fields $current_f:ident, $($tail_f:ident),+;
490        @middle_types $($middle_t_acc:ident),*; @middle_fields $($middle_f_acc:ident),*; // Accumulated middle types/fields so far
491    ) => {
492        impl_swap_start_end!(@internal_swap
493            $struct_name; $proc_ty; $proc_err_ty;
494            $orig_first_t; $orig_first_f;
495            // Continue processing with the tail of the lists:
496            @process_types $($tail_t),+; @process_fields $($tail_f),+;
497            // Add the 'current' type and field to their respective accumulators for middle elements:
498            @middle_types $($middle_t_acc,)* $current_t;
499            @middle_fields $($middle_f_acc,)* $current_f;
500        );
501    };
502
503    // Internal rule: Base case for recursion
504    // This rule is matched when exactly one element remains in the @process_types/@process_fields lists.
505    // This single remaining element is the 'last' element of the original list.
506    (@internal_swap
507        $struct_name:ident; $proc_ty:ty; $proc_err_ty:ty; // Fixed parameters
508        $first_t:ident; $first_f:ident;                   // Original first type ($orig_first_t) and field ($orig_first_f)
509        // The last type and field from the original lists:
510        @process_types $last_t:ident; @process_fields $last_f:ident;
511        // All accumulated middle types and fields:
512        @middle_types $($middle_t_acc:ident),*; @middle_fields $($middle_f_acc:ident),*;
513    ) => {
514        // Generate the trait implementation
515        // The generic parameters for the struct are: original first, all middles, original last
516        impl<
517            $first_t: InPlaceStatefulProcessor<$proc_ty, $proc_err_ty>,
518            $($middle_t_acc: InPlaceStatefulProcessor<$proc_ty, $proc_err_ty>,)*
519            $last_t: InPlaceStatefulProcessor<$proc_ty, $proc_err_ty>
520        > type_flow_traits::SwapStartEnd for $struct_name<$first_t, $($middle_t_acc,)* $last_t> {
521            // The Output type has the first and last type parameters swapped
522            type Output = $struct_name<$last_t, $($middle_t_acc,)* $first_t>;
523
524            fn swap(self) -> Self::Output {
525                Self::Output {
526                    _marker: std::marker::PhantomData,
527                    // Field assignment:
528                    // The first field of the output struct (named $first_f, now expecting type $last_t)
529                    // gets the value from the original last field (self.$last_f).
530                    $first_f: self.$last_f,
531                    // Middle fields (named $middle_f_acc, expecting type $middle_t_acc)
532                    // get their corresponding original values (self.$middle_f_acc).
533                    $($middle_f_acc: self.$middle_f_acc,)*
534                    // The last field of the output struct (named $last_f, now expecting type $first_t)
535                    // gets the value from the original first field (self.$first_f).
536                    $last_f: self.$first_f
537                }
538            }
539        }
540    };
541    
542}
543
544#[macro_export]
545macro_rules! type_flow_inplace_stateful_processor_pipeline {
546    ($struct_name:ident, $processor_type:ty, $processor_error_type:ty, $($field_name:ident : $type_param:ident),+) => {
547        #[implement_processor_swapping] 
548        pub struct $struct_name<$($type_param: InPlaceStatefulProcessor<$processor_type, $processor_error_type>),*> {
549            _marker: std::marker::PhantomData<($($type_param),*)>,
550            $(
551                $field_name: $type_param,
552            )+
553        }
554        impl<$($type_param: InPlaceStatefulProcessor<$processor_type, $processor_error_type>),*> $struct_name<$($type_param),*> {
555            pub fn new($($field_name: $type_param),+) -> Self {
556                Self {
557                    _marker: std::marker::PhantomData,
558                    $(
559                        $field_name,
560                    )+
561                }
562            }
563        }
564        impl<$($type_param: InPlaceStatefulProcessor<$processor_type, $processor_error_type>),*> InPlaceStatefulProcessor<$processor_type, $processor_error_type> for $struct_name<$($type_param),*> {
565            fn process(&mut self, data: &mut $processor_type) -> Result<(), $processor_error_type> {
566                $(
567                    self.$field_name.process(data)?;
568                )*
569                Ok(())
570            }
571        }
572        // Added trait implementations
573        impl_shift_left!($struct_name, ($($type_param),+), ($($field_name),+), $processor_type, $processor_error_type);
574        impl_shift_right!($struct_name, ($($type_param),+), ($($field_name),+), $processor_type, $processor_error_type);
575        impl_swap_start_end!($struct_name, ($($type_param),+), ($($field_name),+), $processor_type, $processor_error_type);
576
577    };
578    //Version that doesn't require you to name the field and generic type param
579    ($struct_name:ident, $processor_common_type:ty, $processor_error_type:ty, $($param_and_field_name:ident),+) => {
580        #[allow(non_snake_case)]
581        pub struct $struct_name<$($param_and_field_name: InPlaceStatefulProcessor<$processor_common_type, $processor_error_type>),*> {
582            _marker: std::marker::PhantomData<($($param_and_field_name),*)>,
583            $(
584                // Using the same ident for field name and its type (which is the generic param)
585                $param_and_field_name: $param_and_field_name,
586            )+ 
587        }
588        impl<$($param_and_field_name: InPlaceStatefulProcessor<$processor_common_type, $processor_error_type>),*> $struct_name<$($param_and_field_name),*> {
589            #[allow(non_snake_case)]
590            pub fn new($($param_and_field_name: $param_and_field_name),+) -> Self {
591                Self { 
592                    _marker: std::marker::PhantomData,
593                    $(
594                        $param_and_field_name,
595                    )+ 
596                } 
597            } 
598        }
599        impl<$($param_and_field_name: InPlaceStatefulProcessor<$processor_common_type, $processor_error_type>),*> InPlaceStatefulProcessor<$processor_common_type, $processor_error_type> for $struct_name<$($param_and_field_name),*> {
600            fn process(&mut self, data: &mut $processor_common_type) -> Result<(), $processor_error_type> {
601                $(
602                    self.$param_and_field_name.process(data)?;
603                )* 
604                Ok(()) 
605            }
606        }
607        // Added trait implementations
608        //impl_shift_left!($struct_name, ($($param_and_field_name),+), ($($param_and_field_name),+), $processor_common_type, $processor_error_type);
609        //impl_shift_right!($struct_name, ($($param_and_field_name),+), ($($param_and_field_name),+), $processor_common_type, $processor_error_type);
610        //impl_swap_start_end!($struct_name, ($($param_and_field_name),+), ($($param_and_field_name),+), $processor_common_type, $processor_error_type);
611
612    };
613}
614
615#[cfg(test)]
616mod tests {
617    use type_flow_proc_macros::implement_processor_swapping;
618    use type_flow_traits::{ShiftLeft, ShiftRight, SwapStartEnd};
619    use super::*;
620
621    processor!(AddFive, String, |s: String| s + "5");
622
623    #[test]
624    fn it_works() {
625        let result = AddFive::process(String::from("test"));
626        assert_eq!(result, "test5");
627    }
628
629    inplace_processor!(InplaceAddHash, String, TestError, |s: &mut String| {
630        s.push_str("#");
631        Ok(())
632    });
633
634    inplace_processor!(InplaceAddStar, String, TestError, |s: &mut String| {
635        s.push_str("*");
636        Ok(())
637    });
638
639    inplace_processor_pipeline!(InplacePipeline, String, TestError, InplaceAddHash, InplaceAddStar);
640
641    #[test]
642    fn test_inplace_pipeline() {
643        let mut test_string = String::from("test");
644        InplacePipeline::process(&mut test_string).unwrap();
645        assert_eq!(test_string, "test#*");
646    }
647
648    inplace_processor!(ErrorProcessor, String, TestError, |_: &mut String| {
649        Err(TestError::SomeError)
650    });
651
652    inplace_processor_pipeline!(ErrorPipeline, String, TestError, InplaceAddHash, ErrorProcessor, InplaceAddStar);
653
654    #[test]
655    fn test_error_pipeline() {
656        let mut test_string = String::from("test");
657        assert_eq!(ErrorPipeline::process(&mut test_string), Err(TestError::SomeError));
658        assert_eq!(test_string, "test#");  // First processor executed before error
659    }
660
661    transform_processor!(SafeConvertToInt, String, i32, |s: String| s.parse::<i32>().unwrap_or(0));
662    
663    #[test]
664    fn it_works_2() {
665        let result = SafeConvertToInt::process(String::from("123"));
666        assert_eq!(result, 123);
667    }
668    
669    stateful_processor!(CountOfInvocations, u32, String, |state: &mut u32, s: String| {
670        *state += 1;
671        format!("{}: {}", s, state)
672    });
673
674    #[test]
675    fn it_works_3() {
676        let mut processor = CountOfInvocations::new(5);
677        let result = processor.process(String::from("Count"));
678        assert_eq!(result, "Count: 6"); // The state is incremented, so the expected output should be 6.
679    }
680    
681    stateful_processor!(FixedMultiply, u64, 10, String, |state:&mut u64, s: String| {
682        *state *= 3;
683        format!("{} fixed: {}", s, state)
684    });
685
686    #[test]
687    fn it_works_4() {
688        let mut processor = FixedMultiply::instance();
689        let result = processor.process(String::from("Counter"));
690        assert_eq!(result, "Counter fixed: 30");
691    }
692    
693    processor!(Reverse, String, |s: String| s.chars().rev().collect::<String>());
694    processor_pipeline!(StatelessPipeline, String, AddFive, Reverse);
695    #[test]
696    fn it_works_5() {
697        let result = StatelessPipeline::process(String::from("test"));
698        assert_eq!(result, "5tset");
699    }
700
701    processor_pipeline!(DoubleStatelessPipeline, String, StatelessPipeline, StatelessPipeline);
702    
703    #[test]
704    fn it_works_6() {
705        let result = DoubleStatelessPipeline::process(String::from("test"));
706        assert_eq!(result, "5test5");
707    }
708
709    stateful_processor!(LetterAtoZPlacer, char, 'A', String, |state:&mut char, s: String| {
710        if *state == 'Z' {
711            *state = 'A';
712        } else {
713            *state = (*state as u8 + 1) as char;
714        }
715        format!("{}: {}", s, state)
716    });
717    #[test]
718    fn it_works_7() {
719        let mut processor = LetterAtoZPlacer::instance();
720        let result = processor.process(String::from("A"));
721        assert_eq!(result, "A: B");
722    }
723    
724    stateful_processor_pipeline!(WeirdStuff, String, a : LetterAtoZPlacer, b : FixedMultiply);
725    
726    #[test]
727    fn it_works_8() {
728        let processor_a = LetterAtoZPlacer::instance();
729        let processor_b = FixedMultiply::instance();
730        let mut pipeline = WeirdStuff::new(processor_a, processor_b);
731        let result = pipeline.process(String::from("B"));
732        assert_eq!(result, "B: B fixed: 30");
733        let result = pipeline.process(String::from("C"));
734        assert_eq!(result, "C: C fixed: 90");
735        let result = pipeline.process(String::from("D"));
736        assert_eq!(result, "D: D fixed: 270");
737        let result = pipeline.process(String::from("E"));
738        assert_eq!(result, "E: E fixed: 810");
739        let result = pipeline.process(String::from("F"));
740        assert_eq!(result, "F: F fixed: 2430");
741        let result = pipeline.process(String::from("G"));
742        assert_eq!(result, "G: G fixed: 7290");
743        let result = pipeline.process(String::from("H"));
744        assert_eq!(result, "H: H fixed: 21870");
745        let result = pipeline.process(String::from("I"));
746        assert_eq!(result, "I: I fixed: 65610");
747        let result = pipeline.process(String::from("J"));
748        assert_eq!(result, "J: J fixed: 196830");
749        let _ = pipeline.process(String::from("K"));
750        let _ = pipeline.process(String::from("L"));
751        let _ = pipeline.process(String::from("M"));
752        let _ = pipeline.process(String::from("N"));
753        let _ = pipeline.process(String::from("O"));
754        let _ = pipeline.process(String::from("P"));
755        let _ = pipeline.process(String::from("Q"));
756        let _ = pipeline.process(String::from("R"));
757        let _ = pipeline.process(String::from("S"));
758        let _ = pipeline.process(String::from("T"));
759        let _ = pipeline.process(String::from("U"));    
760        let _ = pipeline.process(String::from("V"));
761        let _ = pipeline.process(String::from("W"));
762        let _ = pipeline.process(String::from("X"));
763        let _ = pipeline.process(String::from("Y"));
764        let result = pipeline.process(String::from("Z"));
765        assert_eq!(result, "Z: Z fixed: 8472886094430");
766        let result = pipeline.process(String::from("A"));
767        assert_eq!(result, "A: A fixed: 25418658283290");
768    }
769
770    type_flow_processor_pipeline!(Test, String, P1, P2, P3);
771    #[test]
772    fn it_works_9() {
773        //let that_thing: Test<AddFive, Reverse> = Test::<AddFive, Reverse> {  };
774        let result = Test::<AddFive, Reverse, Test<AddFive, Reverse, AddFive>>::process(String::from("stuff"));
775        assert_eq!(result, "5stuff55");
776    }
777
778    stateful_processor_pipeline!(SuffWeird, String, WeirdStuff, WeirdStuff);
779
780    #[test]
781    fn it_works_10() {
782        let mut pipeline = SuffWeird::new(WeirdStuff::new(LetterAtoZPlacer::instance(), FixedMultiply::instance()), WeirdStuff::new(LetterAtoZPlacer::instance(), FixedMultiply::instance()));
783        let result = pipeline.process(String::from("stuff"));
784        assert_eq!(result, "stuff: B fixed: 30: B fixed: 30");
785    }
786
787    #[derive(Debug, PartialEq)]
788    pub enum TestError {
789        SomeError,
790    }
791
792    inplace_processor!(InplaceAddFive, String, TestError, |s: &mut String| {
793        s.push_str("5");
794        Ok(())
795    });
796
797    inplace_processor!(InplaceReverse, String, TestError, |s: &mut String| {
798        *s = s.chars().rev().collect::<String>();
799        Ok(())
800    });
801
802    type_flow_inplace_processor_pipeline!(
803        InplaceTestPipeline,
804        String,
805        TestError,
806        P1,
807        P2,
808        P3
809    );
810
811    #[test]
812    fn it_works_inplace() {
813        let mut data = String::from("stuff");
814        let result = InplaceTestPipeline::<InplaceAddFive, InplaceReverse, InplaceAddFive>::process(&mut data);
815        assert_eq!(result, Ok(()));
816        assert_eq!(data, "5ffuts5");
817    }
818
819    inplace_stateful_processor!(CountUp, u32, String, TestError, |state: &mut u32, s: &mut String| {
820        *state += 1;
821        s.push_str(state.to_string().as_str());
822        Ok(())
823    });
824    inplace_stateful_processor!(ToggleCase, bool, String, TestError, |state: &mut bool, s: &mut String| {
825        *state = !*state;
826        if *state {
827            s.make_ascii_uppercase();
828        } else {
829            s.make_ascii_lowercase();
830        }
831        Ok(())
832    });
833    inplace_stateful_processor_pipeline!(InplaceStatefulProcessorPipeline, String, TestError, CountUp, ToggleCase);
834    #[test]
835    fn it_works_inplace_stateful_pipeline() {
836        let mut pipeline = InplaceStatefulProcessorPipeline::new(CountUp::new(0), ToggleCase::new(false));
837        let mut data = String::from("stuff");
838        let result = pipeline.process(&mut data);
839        assert_eq!(result, Ok(()));
840        assert_eq!(data, "STUFF1");
841        let result = pipeline.process(&mut data);
842        assert_eq!(result, Ok(()));
843        assert_eq!(data, "stuff12");
844    }
845
846    inplace_stateful_processor!(InplaceAddExclamation, (), String, TestError, |_, s: &mut String| {
847        s.push_str("!");
848        Ok(())
849    });
850
851    inplace_stateful_processor!(InplaceAddQuestion, (), String, TestError, |_, s: &mut String| {
852        s.push_str("?");
853        Ok(())
854    });
855
856    type_flow_inplace_stateful_processor_pipeline!(
857        InplaceStatefulTypeFlowPipeline,
858        String,
859        TestError,
860        A,
861        B
862    );
863
864    #[test]
865    fn test_inplace_type_flow_pipeline() {
866        let p1 = InplaceAddExclamation::new(());
867        let p2 = InplaceAddQuestion::new(());
868        let mut pipeline = InplaceStatefulTypeFlowPipeline::<InplaceAddExclamation, InplaceAddQuestion>::new(p1, p2);
869        let mut test_string = "Hello".to_string();
870        pipeline.process(&mut test_string).unwrap();
871        assert_eq!(test_string, "Hello!?");
872    }
873
874    inplace_stateful_processor!(LimitedProcessor, u32, 0, String, TestError, |state: &mut u32, s: &mut String| {
875        if *state >= 5 {
876            Err(TestError::SomeError)
877        } else {
878            *state += 1;
879            s.push_str(&format!(" #{}", state));
880            Ok(())
881        }
882    });
883
884    #[test]
885    fn test_limited_processor() {
886        let mut processor = LimitedProcessor::instance();
887        let mut test_string = String::from("Test");
888        for i in 1..=5 {
889            processor.process(&mut test_string).unwrap();
890            assert_eq!(test_string, format!("Test #{}", (1..=i).map(|num| num.to_string()).collect::<Vec<String>>().join(" #")));
891        }
892        assert_eq!(processor.process(&mut test_string), Err(TestError::SomeError));
893    }
894
895    
896    type_flow_inplace_stateful_processor_pipeline!(WhyNotNow, String, TestError, a : A, b : B, c : C);
897
898    #[test]
899    fn test_type_flow_inplace_stateful_processor_pipeline() {
900        let mut go_with_the_flow = WhyNotNow::<ToggleCase, InplaceAddExclamation, LimitedProcessor>::new(ToggleCase::new(false), InplaceAddExclamation::new(()), LimitedProcessor::instance());
901        let mut test_string = String::from("Test");
902        go_with_the_flow.process(&mut test_string).unwrap();
903        assert_eq!(test_string, "TEST! #1");
904        let mut swapped = go_with_the_flow.swap();
905        swapped.process(&mut test_string).unwrap();
906        assert_eq!(test_string, "test! #1 #2!");
907        let mut shifted_left = swapped.shift_left();
908        shifted_left.process(&mut test_string).unwrap();
909        assert_eq!(test_string, "TEST! #1 #2!! #3");
910        let mut shifted_right = shifted_left.shift_right();
911        let _ = shifted_right.process(&mut test_string);
912        let _ = shifted_right.process(&mut test_string);
913        assert_eq!(shifted_right.process(&mut test_string), Err(TestError::SomeError));
914        let mut something = <WhyNotNow<LimitedProcessor, InplaceAddExclamation, ToggleCase> as SwapArbitraryProcessors<0, 1>>::swap_processors(shifted_right);
915        assert_eq!(something.process(&mut test_string), Err(TestError::SomeError));
916    }
917}