macro_rules! generate_pattern_iterators {
    {
        // Forward iterator
        forward:
            $(#[$forward_iterator_attribute:meta])*
            struct $forward_iterator:ident;

        // Reverse iterator
        reverse:
            $(#[$reverse_iterator_attribute:meta])*
            struct $reverse_iterator:ident;

        // Stability of all generated items
        stability:
            $(#[$common_stability_attribute:meta])*

        // Internal almost-iterator that is being delegated to
        internal:
            $internal_iterator:ident yielding ($iterty:ty);

        // Kind of delegation - either single ended or double ended
        delegate $($t:tt)*
    } => { ... };
    {
        double ended; with $(#[$common_stability_attribute:meta])*,
                           $forward_iterator:ident,
                           $reverse_iterator:ident, $iterty:ty
    } => { ... };
    {
        single ended; with $(#[$common_stability_attribute:meta])*,
                           $forward_iterator:ident,
                           $reverse_iterator:ident, $iterty:ty
    } => { ... };
}
Expand description

This macro generates two public iterator structs wrapping a private internal one that makes use of the Pattern API.

For all patterns P: Pattern<'a> the following items will be generated (generics omitted):

struct $forward_iterator($internal_iterator); struct $reverse_iterator($internal_iterator);

impl Iterator for $forward_iterator { /* internal ends up calling Searcher::next_match() */ }

impl DoubleEndedIterator for $forward_iterator where P::Searcher: DoubleEndedSearcher { /* internal ends up calling Searcher::next_match_back() */ }

impl Iterator for $reverse_iterator where P::Searcher: ReverseSearcher { /* internal ends up calling Searcher::next_match_back() */ }

impl DoubleEndedIterator for $reverse_iterator where P::Searcher: DoubleEndedSearcher { /* internal ends up calling Searcher::next_match() */ }

The internal one is defined outside the macro, and has almost the same semantic as a DoubleEndedIterator by delegating to pattern::Searcher and pattern::ReverseSearcher for both forward and reverse iteration.

“Almost”, because a Searcher and a ReverseSearcher for a given Pattern might not return the same elements, so actually implementing DoubleEndedIterator for it would be incorrect. (See the docs in str::pattern for more details)

However, the internal struct still represents a single ended iterator from either end, and depending on pattern is also a valid double ended iterator, so the two wrapper structs implement Iterator and DoubleEndedIterator depending on the concrete pattern type, leading to the complex impls seen above.