stable_pattern/
split.rs

1//! Iterators for `str` methods.
2
3use core::fmt;
4use core::iter::FusedIterator;
5
6
7use super::pattern::Pattern;
8use super::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
9
10/// This macro generates a Clone impl for string pattern API
11/// wrapper types of the form X<'a, P>
12macro_rules! derive_pattern_clone {
13    (clone $t:ident with |$s:ident| $e:expr) => {
14        impl<'a, P> Clone for $t<'a, P>
15        where
16            P: Pattern<'a>, <P as Pattern<'a>>::Searcher: Clone
17        {
18            fn clone(&self) -> Self {
19                let $s = self;
20                $e
21            }
22        }
23    };
24}
25
26/// This macro generates two public iterator structs
27/// wrapping a private internal one that makes use of the `Pattern` API.
28///
29/// For all patterns `P: Pattern<'a>` the following items will be
30/// generated (generics omitted):
31///
32/// struct $forward_iterator($internal_iterator);
33/// struct $reverse_iterator($internal_iterator);
34///
35/// impl Iterator for $forward_iterator
36/// { /* internal ends up calling Searcher::next_match() */ }
37///
38/// impl DoubleEndedIterator for $forward_iterator
39///       where P::Searcher: DoubleEndedSearcher
40/// { /* internal ends up calling Searcher::next_match_back() */ }
41///
42/// impl Iterator for $reverse_iterator
43///       where P::Searcher: ReverseSearcher
44/// { /* internal ends up calling Searcher::next_match_back() */ }
45///
46/// impl DoubleEndedIterator for $reverse_iterator
47///       where P::Searcher: DoubleEndedSearcher
48/// { /* internal ends up calling Searcher::next_match() */ }
49///
50/// The internal one is defined outside the macro, and has almost the same
51/// semantic as a DoubleEndedIterator by delegating to `pattern::Searcher` and
52/// `pattern::ReverseSearcher` for both forward and reverse iteration.
53///
54/// "Almost", because a `Searcher` and a `ReverseSearcher` for a given
55/// `Pattern` might not return the same elements, so actually implementing
56/// `DoubleEndedIterator` for it would be incorrect.
57/// (See the docs in `str::pattern` for more details)
58///
59/// However, the internal struct still represents a single ended iterator from
60/// either end, and depending on pattern is also a valid double ended iterator,
61/// so the two wrapper structs implement `Iterator`
62/// and `DoubleEndedIterator` depending on the concrete pattern type, leading
63/// to the complex impls seen above.
64macro_rules! generate_pattern_iterators {
65    {
66        // Forward iterator
67        forward:
68            $(#[$forward_iterator_attribute:meta])*
69            struct $forward_iterator:ident;
70
71        // Reverse iterator
72        reverse:
73            $(#[$reverse_iterator_attribute:meta])*
74            struct $reverse_iterator:ident;
75
76        // Internal almost-iterator that is being delegated to
77        internal:
78            $internal_iterator:ident yielding ($iterty:ty);
79
80        // Kind of delegation - either single ended or double ended
81        delegate $($t:tt)*
82    } => {
83        $(#[$forward_iterator_attribute])*
84        pub struct $forward_iterator<'a, P: Pattern<'a>>(pub $internal_iterator<'a, P>);
85
86        impl<'a, P> fmt::Debug for $forward_iterator<'a, P>
87        where
88            P: Pattern<'a>, <P as Pattern<'a>>::Searcher: fmt::Debug,
89        {
90            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91                f.debug_tuple(stringify!($forward_iterator))
92                    .field(&self.0)
93                    .finish()
94            }
95        }
96
97        impl<'a, P: Pattern<'a>> Iterator for $forward_iterator<'a, P> {
98            type Item = $iterty;
99
100            #[inline]
101            fn next(&mut self) -> Option<$iterty> {
102                self.0.next()
103            }
104        }
105
106        impl<'a, P> Clone for $forward_iterator<'a, P>
107        where
108            P: Pattern<'a>, <P as Pattern<'a>>::Searcher: Clone,
109        {
110            fn clone(&self) -> Self {
111                $forward_iterator(self.0.clone())
112            }
113        }
114
115        $(#[$reverse_iterator_attribute])*
116        pub struct $reverse_iterator<'a, P: Pattern<'a>>(pub $internal_iterator<'a, P>);
117
118        impl<'a, P> fmt::Debug for $reverse_iterator<'a, P>
119        where
120            P: Pattern<'a>, <P as Pattern<'a>>::Searcher: fmt::Debug,
121        {
122            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123                f.debug_tuple(stringify!($reverse_iterator))
124                    .field(&self.0)
125                    .finish()
126            }
127        }
128
129        impl<'a, P> Iterator for $reverse_iterator<'a, P>
130        where
131            P: Pattern<'a>, <P as Pattern<'a>>::Searcher: ReverseSearcher<'a>,
132        {
133            type Item = $iterty;
134
135            #[inline]
136            fn next(&mut self) -> Option<$iterty> {
137                self.0.next_back()
138            }
139        }
140
141        impl<'a, P> Clone for $reverse_iterator<'a, P>
142        where
143            P: Pattern<'a>, <P as Pattern<'a>>::Searcher: Clone,
144        {
145            fn clone(&self) -> Self {
146                $reverse_iterator(self.0.clone())
147            }
148        }
149
150        impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {}
151
152        impl<'a, P> FusedIterator for $reverse_iterator<'a, P>
153        where
154            P: Pattern<'a>, <P as Pattern<'a>>::Searcher: ReverseSearcher<'a>,
155        {}
156
157        generate_pattern_iterators!($($t)* with $forward_iterator, $reverse_iterator, $iterty);
158    };
159    {
160        double ended; with $forward_iterator:ident,
161                           $reverse_iterator:ident, $iterty:ty
162    } => {
163        impl<'a, P> DoubleEndedIterator for $forward_iterator<'a, P>
164        where
165            P: Pattern<'a>, <P as Pattern<'a>>::Searcher: DoubleEndedSearcher<'a>,
166        {
167            #[inline]
168            fn next_back(&mut self) -> Option<$iterty> {
169                self.0.next_back()
170            }
171        }
172
173        impl<'a, P> DoubleEndedIterator for $reverse_iterator<'a, P>
174        where
175            P: Pattern<'a>, <P as Pattern<'a>>::Searcher: DoubleEndedSearcher<'a>,
176        {
177            #[inline]
178            fn next_back(&mut self) -> Option<$iterty> {
179                self.0.next()
180            }
181        }
182    };
183    {
184        single ended; with $forward_iterator:ident,
185                           $reverse_iterator:ident, $iterty:ty
186    } => {}
187}
188
189derive_pattern_clone! {
190    clone SplitInternal
191    with |s| SplitInternal { matcher: s.matcher.clone(), ..*s }
192}
193
194pub struct SplitInternal<'a, P: Pattern<'a>> {
195    pub start: usize,
196    pub end: usize,
197    pub matcher: P::Searcher,
198    pub allow_trailing_empty: bool,
199    pub finished: bool,
200}
201
202impl<'a, P> fmt::Debug for SplitInternal<'a, P>
203where
204    P: Pattern<'a>, <P as Pattern<'a>>::Searcher: fmt::Debug,
205{
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        f.debug_struct("SplitInternal")
208            .field("start", &self.start)
209            .field("end", &self.end)
210            .field("matcher", &self.matcher)
211            .field("allow_trailing_empty", &self.allow_trailing_empty)
212            .field("finished", &self.finished)
213            .finish()
214    }
215}
216
217impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
218    #[inline]
219    fn get_end(&mut self) -> Option<&'a str> {
220        if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) {
221            self.finished = true;
222            // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
223            unsafe {
224                let string = self.matcher.haystack().get_unchecked(self.start..self.end);
225                Some(string)
226            }
227        } else {
228            None
229        }
230    }
231
232    #[inline]
233    fn next(&mut self) -> Option<&'a str> {
234        if self.finished {
235            return None;
236        }
237
238        let haystack = self.matcher.haystack();
239        match self.matcher.next_match() {
240            // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries.
241            Some((a, b)) => unsafe {
242                let elt = haystack.get_unchecked(self.start..a);
243                self.start = b;
244                Some(elt)
245            },
246            None => self.get_end(),
247        }
248    }
249
250    #[inline]
251    #[allow(dead_code)]
252    fn next_inclusive(&mut self) -> Option<&'a str> {
253        if self.finished {
254            return None;
255        }
256
257        let haystack = self.matcher.haystack();
258        match self.matcher.next_match() {
259            // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary,
260            // and self.start is either the start of the original string,
261            // or `b` was assigned to it, so it also lies on unicode boundary.
262            Some((_, b)) => unsafe {
263                let elt = haystack.get_unchecked(self.start..b);
264                self.start = b;
265                Some(elt)
266            },
267            None => self.get_end(),
268        }
269    }
270
271    #[inline]
272    fn next_back(&mut self) -> Option<&'a str>
273    where
274        P::Searcher: ReverseSearcher<'a>,
275    {
276        if self.finished {
277            return None;
278        }
279
280        if !self.allow_trailing_empty {
281            self.allow_trailing_empty = true;
282            match self.next_back() {
283                Some(elt) if !elt.is_empty() => return Some(elt),
284                _ => {
285                    if self.finished {
286                        return None;
287                    }
288                }
289            }
290        }
291
292        let haystack = self.matcher.haystack();
293        match self.matcher.next_match_back() {
294            // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries.
295            Some((a, b)) => unsafe {
296                let elt = haystack.get_unchecked(b..self.end);
297                self.end = a;
298                Some(elt)
299            },
300            // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
301            None => unsafe {
302                self.finished = true;
303                Some(haystack.get_unchecked(self.start..self.end))
304            },
305        }
306    }
307
308    #[inline]
309    #[allow(dead_code)]
310    fn next_back_inclusive(&mut self) -> Option<&'a str>
311    where
312        P::Searcher: ReverseSearcher<'a>,
313    {
314        if self.finished {
315            return None;
316        }
317
318        if !self.allow_trailing_empty {
319            self.allow_trailing_empty = true;
320            match self.next_back_inclusive() {
321                Some(elt) if !elt.is_empty() => return Some(elt),
322                _ => {
323                    if self.finished {
324                        return None;
325                    }
326                }
327            }
328        }
329
330        let haystack = self.matcher.haystack();
331        match self.matcher.next_match_back() {
332            // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary,
333            // and self.end is either the end of the original string,
334            // or `b` was assigned to it, so it also lies on unicode boundary.
335            Some((_, b)) => unsafe {
336                let elt = haystack.get_unchecked(b..self.end);
337                self.end = b;
338                Some(elt)
339            },
340            // SAFETY: self.start is either the start of the original string,
341            // or start of a substring that represents the part of the string that hasn't
342            // iterated yet. Either way, it is guaranteed to lie on unicode boundary.
343            // self.end is either the end of the original string,
344            // or `b` was assigned to it, so it also lies on unicode boundary.
345            None => unsafe {
346                self.finished = true;
347                Some(haystack.get_unchecked(self.start..self.end))
348            },
349        }
350    }
351
352    #[inline]
353    fn as_str(&self) -> &'a str {
354        // `Self::get_end` doesn't change `self.start`
355        if self.finished {
356            return "";
357        }
358
359        // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
360        unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }
361    }
362}
363
364generate_pattern_iterators! {
365    forward:
366        /// Created with the method [`split`].
367        ///
368        /// [`split`]: str::split
369        struct Split;
370    reverse:
371        /// Created with the method [`rsplit`].
372        ///
373        /// [`rsplit`]: str::rsplit
374        struct RSplit;
375    internal:
376        SplitInternal yielding (&'a str);
377    delegate double ended;
378}
379
380impl<'a, P: Pattern<'a>> Split<'a, P> {
381    /// Returns remainder of the splitted string
382    ///
383    /// # Examples
384    ///
385    /// ```
386    /// let mut split = "Mary had a little lamb".split(' ');
387    /// assert_eq!(split.as_str(), "Mary had a little lamb");
388    /// split.next();
389    /// assert_eq!(split.as_str(), "had a little lamb");
390    /// split.by_ref().for_each(drop);
391    /// assert_eq!(split.as_str(), "");
392    /// ```
393    #[inline]
394    pub fn as_str(&self) -> &'a str {
395        self.0.as_str()
396    }
397}
398
399impl<'a, P: Pattern<'a>> RSplit<'a, P> {
400    /// Returns remainder of the splitted string
401    ///
402    /// # Examples
403    ///
404    /// ```
405    /// let mut split = "Mary had a little lamb".rsplit(' ');
406    /// assert_eq!(split.as_str(), "Mary had a little lamb");
407    /// split.next();
408    /// assert_eq!(split.as_str(), "Mary had a little");
409    /// split.by_ref().for_each(drop);
410    /// assert_eq!(split.as_str(), "");
411    /// ```
412    #[inline]
413    pub fn as_str(&self) -> &'a str {
414        self.0.as_str()
415    }
416}
417
418generate_pattern_iterators! {
419    forward:
420        /// Created with the method [`split_terminator`].
421        ///
422        /// [`split_terminator`]: str::split_terminator
423        struct SplitTerminator;
424    reverse:
425        /// Created with the method [`rsplit_terminator`].
426        ///
427        /// [`rsplit_terminator`]: str::rsplit_terminator
428        struct RSplitTerminator;
429    internal:
430        SplitInternal yielding (&'a str);
431    delegate double ended;
432}
433
434impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
435    /// Returns remainder of the splitted string
436    ///
437    /// # Examples
438    ///
439    /// ```
440    /// let mut split = "A..B..".split_terminator('.');
441    /// assert_eq!(split.as_str(), "A..B..");
442    /// split.next();
443    /// assert_eq!(split.as_str(), ".B..");
444    /// split.by_ref().for_each(drop);
445    /// assert_eq!(split.as_str(), "");
446    /// ```
447    #[inline]
448    pub fn as_str(&self) -> &'a str {
449        self.0.as_str()
450    }
451}
452
453impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
454    /// Returns remainder of the splitted string
455    ///
456    /// # Examples
457    ///
458    /// ```
459    /// let mut split = "A..B..".rsplit_terminator('.');
460    /// assert_eq!(split.as_str(), "A..B..");
461    /// split.next();
462    /// assert_eq!(split.as_str(), "A..B");
463    /// split.by_ref().for_each(drop);
464    /// assert_eq!(split.as_str(), "");
465    /// ```
466    #[inline]
467    pub fn as_str(&self) -> &'a str {
468        self.0.as_str()
469    }
470}
471
472derive_pattern_clone! {
473    clone SplitNInternal
474    with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
475}
476
477pub struct SplitNInternal<'a, P: Pattern<'a>> {
478    pub iter: SplitInternal<'a, P>,
479    /// The number of splits remaining
480    pub count: usize,
481}
482
483impl<'a, P> fmt::Debug for SplitNInternal<'a, P>
484where
485    P: Pattern<'a>, <P as Pattern<'a>>::Searcher: fmt::Debug,
486{
487    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
488        f.debug_struct("SplitNInternal")
489            .field("iter", &self.iter)
490            .field("count", &self.count)
491            .finish()
492    }
493}
494
495impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
496    #[inline]
497    fn next(&mut self) -> Option<&'a str> {
498        match self.count {
499            0 => None,
500            1 => {
501                self.count = 0;
502                self.iter.get_end()
503            }
504            _ => {
505                self.count -= 1;
506                self.iter.next()
507            }
508        }
509    }
510
511    #[inline]
512    fn next_back(&mut self) -> Option<&'a str>
513    where
514        P::Searcher: ReverseSearcher<'a>,
515    {
516        match self.count {
517            0 => None,
518            1 => {
519                self.count = 0;
520                self.iter.get_end()
521            }
522            _ => {
523                self.count -= 1;
524                self.iter.next_back()
525            }
526        }
527    }
528
529    #[inline]
530    fn as_str(&self) -> &'a str {
531        self.iter.as_str()
532    }
533}
534
535generate_pattern_iterators! {
536    forward:
537        /// Created with the method [`splitn`].
538        ///
539        /// [`splitn`]: str::splitn
540        struct SplitN;
541    reverse:
542        /// Created with the method [`rsplitn`].
543        ///
544        /// [`rsplitn`]: str::rsplitn
545        struct RSplitN;
546    internal:
547        SplitNInternal yielding (&'a str);
548    delegate single ended;
549}
550
551impl<'a, P: Pattern<'a>> SplitN<'a, P> {
552    /// Returns remainder of the splitted string
553    ///
554    /// # Examples
555    ///
556    /// ```
557    /// let mut split = "Mary had a little lamb".splitn(3, ' ');
558    /// assert_eq!(split.as_str(), "Mary had a little lamb");
559    /// split.next();
560    /// assert_eq!(split.as_str(), "had a little lamb");
561    /// split.by_ref().for_each(drop);
562    /// assert_eq!(split.as_str(), "");
563    /// ```
564    #[inline]
565    pub fn as_str(&self) -> &'a str {
566        self.0.as_str()
567    }
568}
569
570impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
571    /// Returns remainder of the splitted string
572    ///
573    /// # Examples
574    ///
575    /// ```
576    /// let mut split = "Mary had a little lamb".rsplitn(3, ' ');
577    /// assert_eq!(split.as_str(), "Mary had a little lamb");
578    /// split.next();
579    /// assert_eq!(split.as_str(), "Mary had a little");
580    /// split.by_ref().for_each(drop);
581    /// assert_eq!(split.as_str(), "");
582    /// ```
583    #[inline]
584    pub fn as_str(&self) -> &'a str {
585        self.0.as_str()
586    }
587}
588
589derive_pattern_clone! {
590    clone MatchIndicesInternal
591    with |s| MatchIndicesInternal(s.0.clone())
592}
593
594pub struct MatchIndicesInternal<'a, P: Pattern<'a>>(pub P::Searcher);
595
596impl<'a, P> fmt::Debug for MatchIndicesInternal<'a, P>
597where
598    P: Pattern<'a>, <P as Pattern<'a>>::Searcher: fmt::Debug,
599{
600    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
601        f.debug_tuple("MatchIndicesInternal").field(&self.0).finish()
602    }
603}
604
605impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
606    #[inline]
607    fn next(&mut self) -> Option<(usize, &'a str)> {
608        self.0
609            .next_match()
610            // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
611            .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
612    }
613
614    #[inline]
615    fn next_back(&mut self) -> Option<(usize, &'a str)>
616    where
617        P::Searcher: ReverseSearcher<'a>,
618    {
619        self.0
620            .next_match_back()
621            // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
622            .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
623    }
624}
625
626generate_pattern_iterators! {
627    forward:
628        /// Created with the method [`match_indices`].
629        ///
630        /// [`match_indices`]: str::match_indices
631        struct MatchIndices;
632    reverse:
633        /// Created with the method [`rmatch_indices`].
634        ///
635        /// [`rmatch_indices`]: str::rmatch_indices
636        struct RMatchIndices;
637    internal:
638        MatchIndicesInternal yielding ((usize, &'a str));
639    delegate double ended;
640}
641
642derive_pattern_clone! {
643    clone MatchesInternal
644    with |s| MatchesInternal(s.0.clone())
645}
646
647pub struct MatchesInternal<'a, P: Pattern<'a>>(pub P::Searcher);
648
649impl<'a, P> fmt::Debug for MatchesInternal<'a, P>
650where
651    P: Pattern<'a>, <P as Pattern<'a>>::Searcher: fmt::Debug,
652{
653    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
654        f.debug_tuple("MatchesInternal").field(&self.0).finish()
655    }
656}
657
658impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
659    #[inline]
660    fn next(&mut self) -> Option<&'a str> {
661        // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
662        self.0.next_match().map(|(a, b)| unsafe {
663            // Indices are known to be on utf8 boundaries
664            self.0.haystack().get_unchecked(a..b)
665        })
666    }
667
668    #[inline]
669    fn next_back(&mut self) -> Option<&'a str>
670    where
671        P::Searcher: ReverseSearcher<'a>,
672    {
673        // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
674        self.0.next_match_back().map(|(a, b)| unsafe {
675            // Indices are known to be on utf8 boundaries
676            self.0.haystack().get_unchecked(a..b)
677        })
678    }
679}
680
681generate_pattern_iterators! {
682    forward:
683        /// Created with the method [`matches`].
684        ///
685        /// [`matches`]: str::matches
686        struct Matches;
687    reverse:
688        /// Created with the method [`rmatches`].
689        ///
690        /// [`rmatches`]: str::rmatches
691        struct RMatches;
692    internal:
693        MatchesInternal yielding (&'a str);
694    delegate double ended;
695}