@@ -10,9 +10,8 @@ use crate::iter::{Map, Cloned, FusedIterator, TrustedLen, TrustedRandomAccess, F
10
10
use crate :: iter:: { Flatten , FlatMap , Chain } ;
11
11
use crate :: slice:: { self , SliceIndex , Split as SliceSplit } ;
12
12
use crate :: mem;
13
- use crate :: needle:: {
14
- ext, Needle , Searcher , ReverseSearcher , Consumer , ReverseConsumer , DoubleEndedConsumer ,
15
- } ;
13
+ use crate :: needle:: { ext, Needle , Searcher , ReverseSearcher , Consumer , ReverseConsumer , DoubleEndedConsumer } ;
14
+ use crate :: ops:: Range ;
16
15
17
16
#[ unstable( feature = "str_internals" , issue = "0" ) ]
18
17
mod needles;
@@ -2549,6 +2548,105 @@ impl str {
2549
2548
ext:: rfind ( self , pat)
2550
2549
}
2551
2550
2551
+ /// Returns the byte range of the first substring of this string slice that
2552
+ /// the pattern can be found.
2553
+ ///
2554
+ /// Returns [`None`] if the pattern doesn't match.
2555
+ ///
2556
+ /// The pattern can be a `&str`, [`char`], or a closure that determines if
2557
+ /// a substring matches.
2558
+ ///
2559
+ /// [`None`]: option/enum.Option.html#variant.None
2560
+ ///
2561
+ /// # Examples
2562
+ ///
2563
+ /// Simple patterns:
2564
+ ///
2565
+ /// ```
2566
+ /// let s = "Löwe 老虎 Léopard";
2567
+ ///
2568
+ /// assert_eq!(s.find_range('L'), Some(0..1));
2569
+ /// assert_eq!(s.find_range('é'), Some(14..16));
2570
+ /// assert_eq!(s.find_range("Léopard"), Some(13..21));
2571
+ /// ```
2572
+ ///
2573
+ /// More complex patterns using point-free style and closures:
2574
+ ///
2575
+ /// ```
2576
+ /// let s = "Löwe 老虎 Léopard";
2577
+ ///
2578
+ /// assert_eq!(s.find(char::is_whitespace), Some(5..6));
2579
+ /// assert_eq!(s.find(char::is_lowercase), Some(1..2));
2580
+ /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1..2));
2581
+ /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4..5));
2582
+ /// ```
2583
+ ///
2584
+ /// Not finding the pattern:
2585
+ ///
2586
+ /// ```
2587
+ /// let s = "Löwe 老虎 Léopard";
2588
+ /// let x: &[_] = &['1', '2'];
2589
+ ///
2590
+ /// assert_eq!(s.find(x), None);
2591
+ /// ```
2592
+ #[ unstable( feature = "str_find_range" , issue = "56345" ) ]
2593
+ #[ inline]
2594
+ pub fn find_range < ' a , P : Needle < & ' a str > > ( & ' a self , pat : P ) -> Option < Range < usize > >
2595
+ where
2596
+ P :: Searcher : Searcher < str > , // FIXME: RFC 2089
2597
+ P :: Consumer : Consumer < str > , // FIXME: RFC 2089
2598
+ {
2599
+ ext:: find_range ( self , pat)
2600
+ }
2601
+
2602
+ /// Returns the byte range of the last substring of this string slice that
2603
+ /// the pattern can be found.
2604
+ ///
2605
+ /// Returns [`None`] if the pattern doesn't match.
2606
+ ///
2607
+ /// The pattern can be a `&str`, [`char`], or a closure that determines if
2608
+ /// a substring matches.
2609
+ ///
2610
+ /// [`None`]: option/enum.Option.html#variant.None
2611
+ ///
2612
+ /// # Examples
2613
+ ///
2614
+ /// Simple patterns:
2615
+ ///
2616
+ /// ```
2617
+ /// let s = "Löwe 老虎 Léopard";
2618
+ ///
2619
+ /// assert_eq!(s.rfind_range('L'), Some(13..14));
2620
+ /// assert_eq!(s.rfind_range('é'), Some(14..16));
2621
+ /// ```
2622
+ ///
2623
+ /// More complex patterns with closures:
2624
+ ///
2625
+ /// ```
2626
+ /// let s = "Löwe 老虎 Léopard";
2627
+ ///
2628
+ /// assert_eq!(s.rfind_range(char::is_whitespace), Some(12..13));
2629
+ /// assert_eq!(s.rfind_range(char::is_lowercase), Some(20..21));
2630
+ /// ```
2631
+ ///
2632
+ /// Not finding the pattern:
2633
+ ///
2634
+ /// ```
2635
+ /// let s = "Löwe 老虎 Léopard";
2636
+ /// let x: &[_] = &['1', '2'];
2637
+ ///
2638
+ /// assert_eq!(s.rfind_range(x), None);
2639
+ /// ```
2640
+ #[ unstable( feature = "str_find_range" , issue = "56345" ) ]
2641
+ #[ inline]
2642
+ pub fn rfind_range < ' a , P : Needle < & ' a str > > ( & ' a self , pat : P ) -> Option < Range < usize > >
2643
+ where
2644
+ P :: Searcher : ReverseSearcher < str > ,
2645
+ P :: Consumer : Consumer < str > , // FIXME: RFC 2089
2646
+ {
2647
+ ext:: rfind_range ( self , pat)
2648
+ }
2649
+
2552
2650
/// An iterator over substrings of this string slice, separated by
2553
2651
/// characters matched by a pattern.
2554
2652
///
@@ -3083,6 +3181,99 @@ impl str {
3083
3181
ext:: rmatch_indices ( self , pat)
3084
3182
}
3085
3183
3184
+ /// An iterator over the disjoint matches of a pattern within this string
3185
+ /// slice as well as the range that the match covers.
3186
+ ///
3187
+ /// For matches of `pat` within `self` that overlap, only the ranges
3188
+ /// corresponding to the first match are returned.
3189
+ ///
3190
+ /// The pattern can be a `&str`, [`char`], or a closure that determines
3191
+ /// if a substring matches.
3192
+ ///
3193
+ /// # Iterator behavior
3194
+ ///
3195
+ /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
3196
+ /// allows a reverse search and forward/reverse search yields the same
3197
+ /// elements. This is true for, eg, [`char`] but not for `&str`.
3198
+ ///
3199
+ /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
3200
+ ///
3201
+ /// If the pattern allows a reverse search but its results might differ
3202
+ /// from a forward search, the [`rmatch_ranges`] method can be used.
3203
+ ///
3204
+ /// [`rmatch_ranges`]: #method.rmatch_ranges
3205
+ ///
3206
+ /// # Examples
3207
+ ///
3208
+ /// Basic usage:
3209
+ ///
3210
+ /// ```
3211
+ /// let v: Vec<_> = "abcXXXabcYYYabc".match_ranges("abc").collect();
3212
+ /// assert_eq!(v, [(0..3, "abc"), (6..9, "abc"), (12..15, "abc")]);
3213
+ ///
3214
+ /// let v: Vec<_> = "1abcabc2".match_ranges("abc").collect();
3215
+ /// assert_eq!(v, [(1..4, "abc"), (4..7, "abc")]);
3216
+ ///
3217
+ /// let v: Vec<_> = "ababa".match_ranges("aba").collect();
3218
+ /// assert_eq!(v, [(0..3, "aba")]); // only the first `aba`
3219
+ /// ```
3220
+ #[ unstable( feature = "str_find_range" , issue = "56345" ) ]
3221
+ #[ inline]
3222
+ pub fn match_ranges < ' a , P > ( & ' a self , pat : P ) -> ext:: MatchRanges < & ' a str , P :: Searcher >
3223
+ where
3224
+ P : Needle < & ' a str > ,
3225
+ P :: Searcher : Searcher < str > , // FIXME: RFC 2089
3226
+ P :: Consumer : Consumer < str > , // FIXME: RFC 2089
3227
+ {
3228
+ ext:: match_ranges ( self , pat)
3229
+ }
3230
+
3231
+ /// An iterator over the disjoint matches of a pattern within `self`,
3232
+ /// yielded in reverse order along with the range of the match.
3233
+ ///
3234
+ /// For matches of `pat` within `self` that overlap, only the ranges
3235
+ /// corresponding to the last match are returned.
3236
+ ///
3237
+ /// The pattern can be a `&str`, [`char`], or a closure that determines if a
3238
+ /// substring matches.
3239
+ ///
3240
+ /// # Iterator behavior
3241
+ ///
3242
+ /// The returned iterator requires that the pattern supports a reverse
3243
+ /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
3244
+ /// search yields the same elements.
3245
+ ///
3246
+ /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
3247
+ ///
3248
+ /// For iterating from the front, the [`match_ranges`] method can be used.
3249
+ ///
3250
+ /// [`match_ranges`]: #method.match_ranges
3251
+ ///
3252
+ /// # Examples
3253
+ ///
3254
+ /// Basic usage:
3255
+ ///
3256
+ /// ```
3257
+ /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_ranges("abc").collect();
3258
+ /// assert_eq!(v, [(12..15, "abc"), (6..9, "abc"), (0..3, "abc")]);
3259
+ ///
3260
+ /// let v: Vec<_> = "1abcabc2".rmatch_ranges("abc").collect();
3261
+ /// assert_eq!(v, [(4..7, "abc"), (1..4, "abc")]);
3262
+ ///
3263
+ /// let v: Vec<_> = "ababa".rmatch_ranges("aba").collect();
3264
+ /// assert_eq!(v, [(2..5, "aba")]); // only the last `aba`
3265
+ /// ```
3266
+ #[ unstable( feature = "str_find_range" , issue = "56345" ) ]
3267
+ #[ inline]
3268
+ pub fn rmatch_ranges < ' a , P > ( & ' a self , pat : P ) -> ext:: RMatchRanges < & ' a str , P :: Searcher >
3269
+ where
3270
+ P : Needle < & ' a str > ,
3271
+ P :: Searcher : ReverseSearcher < str > ,
3272
+ P :: Consumer : Consumer < str > , // FIXME: RFC 2089
3273
+ {
3274
+ ext:: rmatch_ranges ( self , pat)
3275
+ }
3276
+
3086
3277
/// Returns a string slice with leading and trailing whitespace removed.
3087
3278
///
3088
3279
/// 'Whitespace' is defined according to the terms of the Unicode Derived
0 commit comments