konst_macro_rules/iter/
combinator_methods.rs

1#[doc(hidden)]
2#[macro_export]
3macro_rules! __process_iter_args {
4    (
5        $callback_macro:tt
6        $fixed_arguments:tt
7        $other_args:tt
8    ) => (
9        $crate::__::compile_error!{"expected iterator argument"}
10    );
11    (
12        $callback_macro:tt
13        $fixed_arguments:tt
14        $other_args:tt
15        $iter:expr $(, $method:ident $(($($args:tt)*))? )* $(,)*
16        $( => $($rem:tt)*)?
17    ) => ({
18        $(
19            $crate::__cim_assert_has_args!{ $method $(($($args)*))? }
20        )*
21
22        $crate::iter::__cim_preprocess_methods !{
23            (
24                ((iter = $crate::into_iter_macro!($iter));)
25                $callback_macro
26                $fixed_arguments
27                $other_args
28                (
29                    $($method($($($args)*)?),)*
30                    $( => $($rem)* )?
31                )
32            )
33
34            [next]
35
36            $($method $method ($($($args)*)?),)*
37        }
38    });
39    (
40        $callback_macro:tt
41        $fixed_arguments:tt
42        $other_args:tt
43        $iter:expr,
44            $method0:ident $(($($args0:tt)*))?
45            .$method1:ident
46        $($rem:tt)*
47    ) => ({
48        $crate::__::compile_error!{"\
49            iterator methods in this macro are comma-separated\
50        "}
51    })
52}
53
54#[doc(hidden)]
55#[macro_export]
56macro_rules! __call_iter_methods {
57    (
58        $fixed:tt
59        ($vars:tt $macro:tt $prev_args:tt $label:tt next_back $allowed_methods:tt)
60        $item:ident $iters:tt
61        rev($($args:tt)*), $($rem:tt)*
62    ) => ({
63        $crate::__cim_error_on_args!{rev($($args)*)}
64
65        $crate::__call_iter_methods!{
66            ($vars $macro $prev_args $label next $allowed_methods)
67            ($vars $macro $prev_args $label next $allowed_methods)
68            $item
69            $iters
70            $($rem)*
71        }
72    });
73    (
74        $fixed:tt
75        ($vars:tt $macro:tt $prev_args:tt $label:tt next $allowed_methods:tt)
76        $item:ident $iters:tt
77        rev($($args:tt)*), $($rem:tt)*
78    ) => ({
79        $crate::__cim_error_on_args!{rev($($args)*)}
80
81        $crate::__call_iter_methods!{
82            ($vars $macro $prev_args $label next_back $allowed_methods)
83            ($vars $macro $prev_args $label next_back $allowed_methods)
84            $item
85            $iters
86            $($rem)*
87        }
88    });
89    (
90        (
91            $vars:tt
92            $macro:tt
93            $prev_args:tt
94            $label:tt
95            $next_fn:tt
96            $allowed_methods:ident
97        )
98        (($iter_var:ident $($rem_vars:ident)*) $($rem_fixed:tt)*)
99        $item:ident
100        ($($iters:tt)*)
101        zip($($args:tt)*), $($rem:tt)*
102    ) => (
103        $crate::__call_iter_methods!{
104            (($($rem_vars)*) $($rem_fixed)*)
105            (($($rem_vars)*) $($rem_fixed)*)
106            $item
107            ( $($iters)* (
108                {}
109
110                let $item = if let $crate::__::Some((elem_, next_)) = $iter_var.$next_fn() {
111                    $iter_var = next_;
112
113                    ($item, elem_)
114                } else {
115                    $crate::__cim_break!{(($($rem_vars)*) $($rem_fixed)*)}
116                };
117            ))
118
119            $($rem)*
120        }
121    );
122    (
123        $fixed:tt
124        (($iter_var:ident $($rem_vars:ident)*) $($rem_fixed:tt)*)
125        $item:ident ($($iters:tt)*)
126        enumerate($($args:tt)*), $($rem:tt)*
127    ) => ({
128        $crate::__cim_error_on_args!{enumerate($($args)*)}
129
130        $crate::__call_iter_methods!{
131            (($($rem_vars)*) $($rem_fixed)*)
132            (($($rem_vars)*) $($rem_fixed)*)
133            $item
134            ( $($iters)* (
135                {}
136                let $item = ($iter_var, $item);
137                $iter_var+=1;
138            ))
139            $($rem)*
140        }
141    });
142    (
143        $fixed:tt
144        (($var:ident $($rem_vars:ident)*) $($rem_fixed:tt)*)
145        $item:ident
146        ($($iters:tt)*)
147        //``__cim_preprocess_methods` ensures that only one argument is passed
148        take($($args:tt)*), $($rem:tt)*
149    ) => (
150        $crate::__call_iter_methods!{
151            (($($rem_vars)*) $($rem_fixed)*)
152            (($($rem_vars)*) $($rem_fixed)*)
153            $item
154            ( $($iters)* (
155                {}
156                if $var == 0 {
157                    $crate::__cim_break!{$fixed}
158                } else {
159                    $var -= 1;
160                }
161            ))
162            $($rem)*
163        }
164    );
165    (
166        $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*)
167        take_while($($pred:tt)*), $($rem:tt)*
168    ) => (
169        $crate::__call_iter_methods!{
170            $fixed
171            $fixedb
172            $item
173            ( $($iters)* (
174                {}
175                let cond: $crate::__::bool = $crate::utils::__parse_closure_1!(
176                    ($crate::__cim_filter) ($item,) (take_while),
177                    $($pred)*
178                );
179                if !cond {
180                    $crate::__cim_break!{$fixed}
181                }
182            ))
183            $($rem)*
184        }
185    );
186    (
187        $fixed:tt
188        (($var:ident $($rem_vars:ident)*) $($rem_fixed:tt)*)
189        $item:ident ($($iters:tt)*)
190        //``__cim_preprocess_methods` ensures that only one argument is passed
191        skip($($args:tt)*), $($rem:tt)*
192    ) => (
193        $crate::__call_iter_methods!{
194            (($($rem_vars)*) $($rem_fixed)*)
195            (($($rem_vars)*) $($rem_fixed)*)
196            $item
197            ( $($iters)* (
198                {}
199                if $var != 0 {
200                    $var -= 1;
201                    continue;
202                }
203            ))
204            $($rem)*
205        }
206    );
207    (
208        $fixed:tt
209        (($still_skipping:ident $($rem_vars:ident)*) $($rem_fixed:tt)*)
210        $item:ident ($($iters:tt)*)
211        skip_while($($pred:tt)*), $($rem:tt)*
212    ) => (
213        $crate::__call_iter_methods!{
214            (($($rem_vars)*) $($rem_fixed)*)
215            (($($rem_vars)*) $($rem_fixed)*)
216            $item
217            ( $($iters)* (
218                {}
219                $still_skipping = $still_skipping && $crate::utils::__parse_closure_1!(
220                    ($crate::__cim_filter) ($item,) (skip_while),
221                    $($pred)*
222                );
223
224                if $still_skipping {
225                    continue;
226                }
227            ))
228            $($rem)*
229        }
230    );
231    (
232        $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*)
233        filter($($pred:tt)*), $($rem:tt)*
234    ) => (
235        $crate::__call_iter_methods!{
236            $fixed
237            $fixedb
238            $item
239            ( $($iters)* (
240                {}
241                let cond = $crate::utils::__parse_closure_1!(
242                    ($crate::__cim_filter) ($item,) (filter),
243                    $($pred)*
244                );
245                if !cond {
246                    continue;
247                }
248            ))
249            $($rem)*
250        }
251    );
252    (
253        $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*)
254        filter_map($($args:tt)*), $($rem:tt)*
255    ) => (
256        $crate::__call_iter_methods!{
257            $fixed
258            $fixedb
259            $item
260            ( $($iters)* (
261                {}
262                let val: $crate::__::Option<_> = $crate::utils::__parse_closure_1!(
263                    ($crate::__cim_map) ($item,) (filter_map),
264                    $($args)*
265                );
266
267                let $item = match val {
268                    $crate::__::Some(x) => x,
269                    $crate::__::None => continue,
270                };
271            ))
272            $($rem)*
273        }
274    );
275    (
276        $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*)
277        map($($args:tt)*), $($rem:tt)*
278    ) => (
279        $crate::__call_iter_methods!{
280            $fixed
281            $fixedb
282            $item
283            ( $($iters)* (
284                {}
285                let $item = $crate::utils::__parse_closure_1!(
286                    ($crate::__cim_map) ($item,) (map),
287                    $($args)*
288                );
289            ))
290            $($rem)*
291        }
292    );
293    (
294        $fixed:tt $fixedb:tt $item:ident ($($iters:tt)*)
295        copied($($args:tt)*), $($rem:tt)*
296    ) => ({
297        $crate::__cim_error_on_args!{copied($($args)*)}
298
299        $crate::__call_iter_methods!{
300            $fixed
301            $fixedb
302            $item
303            ( $($iters)* (
304                {}
305                let $item = *$item;
306            ))
307            $($rem)*
308        }
309    });
310    (
311        $fixed:tt $fixedb:tt $item:ident $iters:tt
312        flat_map($($args:tt)*), $($rem:tt)*
313    ) => {
314        $crate::__cim_output_layer!{
315            $fixed
316            $item
317            $iters
318            {}
319            {
320                $crate::utils::__parse_closure_1!{
321                    ($crate::__cim_flat_map) ($fixed $item ($($rem)*)) (flat_map),
322                    $($args)*
323                }
324            }
325            {}
326        }
327    };
328    (
329        $fixed:tt $fixedb:tt $item:ident $iters:tt
330        flatten($($args:tt)*), $($rem:tt)*
331    ) => ({
332        $crate::__cim_error_on_args!{flatten($($args)*)}
333        $crate::__cim_output_layer!{
334            $fixed
335            $item
336            $iters
337            {}
338            {
339                $crate::__cim_flat_map! {
340                    $fixed
341                    $item
342                    ($($rem)*)
343                    |elem| elem
344                }
345            }
346            {}
347        }
348    });
349    (
350        $fixed:tt
351        ($vars:tt $macro:tt $prev_args:tt $label:tt $next_fn:tt adapter)
352        $item:tt $iters:tt
353        $comb:ident ($($args:tt)*), $($rem:tt)*
354    ) => {
355        $crate::iter::__cim_method_not_found_err!{$comb $comb}
356    };
357    (
358        $fixed:tt
359        (
360            $vars:tt
361            ($($macro:tt)*)
362            ($($prev_args:tt)*)
363            $label:tt
364            $next_fn:tt
365            consumer
366        )
367        $item:ident
368        $iters:tt
369        $($rem:tt)*
370    ) => {
371        $($macro)* ! {
372            $($prev_args)*
373            ($label $item $iters)
374            $vars
375            $item
376            $($rem)*
377        }
378    };
379    (
380        $fixed:tt
381        ($vars:tt ($($macro:tt)*) ($($prev_args:tt)*) $label:tt $next_fn:tt $allowed_methods:ident)
382        $item:ident
383        $iters:tt
384        $($rem:tt)*
385    ) => {
386        $crate::__cim_output_layer!{
387            $fixed
388            $item
389            $iters
390            {  }
391            { $($macro)* ! {@each $($prev_args)* ($item $allowed_methods), $($rem)*} }
392            { $($macro)* ! {@end $($prev_args)* ($item $allowed_methods), $($rem)*} }
393        }
394    };
395    ($($tt:tt)*) => {
396        $crate::__::compile_error!{$crate::__::concat!(
397            "Unsupported arguments: ",
398            $crate::__::stringify!($($tt)*),
399        )}
400    };
401}
402
403#[doc(hidden)]
404#[macro_export]
405macro_rules! __cim_output_layer {
406    (
407        (
408            $vars:tt
409            $macro:tt
410            $prev_args:tt
411            ($break_label:lifetime $($label:lifetime)?)
412            $next_fn:tt
413            $allowed_methods:ident
414        )
415        $item:ident
416        (
417            $((
418                { $($var:ident = $var_expr:expr),* $(,)? }
419                $($code:tt)*
420            ))*
421        )
422        {$($extra_init:tt)*}
423        $each:tt
424        $finish:tt
425    ) => ({
426        match ($(($($var_expr,)*),)*) {
427            ($(($(mut $var,)*),)*) => {
428                $($extra_init)*
429                $($label:)? loop {
430                    $($($code)*)*
431                    $each
432                }
433                $finish
434            },
435        }
436    });
437}
438
439#[doc(hidden)]
440#[macro_export]
441macro_rules! __cim_filter {
442    ($item:ident, |$elem:pat| $v:expr) => {{
443        let $elem = &$item;
444        // avoiding lifetime extension
445        let v: $crate::__::bool = $v;
446        v
447    }};
448}
449
450#[doc(hidden)]
451#[macro_export]
452macro_rules! __cim_map {
453    ($item:ident, |$elem:pat| $v:expr) => {{
454        let $elem = $item;
455        // allowing for lifetime extension of temporaries
456        $v
457    }};
458}
459
460#[doc(hidden)]
461#[macro_export]
462macro_rules! __cim_break {
463    ((
464        $vars:tt
465        $macro:tt
466        $prev_args:tt
467        ($break_label:tt $($label:tt)?)
468        $next_fn:tt
469        $allowed_methods:ident
470    )) => {
471        break $break_label;
472    };
473}
474
475#[doc(hidden)]
476#[macro_export]
477macro_rules! __cim_flat_map {
478    (
479        (
480            $vars:tt
481            $macro:tt
482            $prev_args:tt
483            ($break_label:tt $($label:tt)?)
484            $next_fn:tt
485            $allowed_methods:ident
486        )
487        $item:ident
488        ($($rem:tt)*)
489        |$elem:pat| $v:expr
490    ) => ({
491        let $elem = $item;
492        $crate::__call_iter_methods!{
493            ($vars $macro $prev_args ($break_label) $next_fn $allowed_methods)
494            ($vars $macro $prev_args ($break_label) $next_fn $allowed_methods)
495            $item
496            (
497                (
498                    {iter = $crate::into_iter_macro!($v)}
499                    let $item = if let $crate::__::Some((elem_, next_)) = iter.$next_fn() {
500                        iter = next_;
501                        elem_
502                    } else {
503                        break;
504                    };
505                )
506            )
507            $($rem)*
508        }
509    });
510
511}
512
513#[doc(hidden)]
514#[macro_export]
515macro_rules! __cim_error_on_args {
516    ($func:ident()) => ();
517    ($func:ident ($($args:tt)*)) => {
518        $crate::__::compile_error!{$crate::__::concat!{
519            "`",
520            $crate::__::stringify!($func),
521            "` does not take arguments, passed: ",
522            $crate::__::stringify!($($args)*),
523        }}
524    };
525}
526
527#[doc(hidden)]
528#[macro_export]
529macro_rules! __cim_assert_has_args {
530    ($func:ident ($($args:tt)*)) => {};
531    ($func:ident) => {
532        $crate::__::compile_error! {$crate::__::concat!{
533            "method call expected arguments: ",
534            $crate::__::stringify!($func),
535        }}
536    };
537}