Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f1bedc3

Browse files
committedApr 19, 2019
Added str::{find_range, rfind_range, match_ranges, rmatch_ranges}.
1 parent 602da5c commit f1bedc3

File tree

1 file changed

+194
-3
lines changed

1 file changed

+194
-3
lines changed
 

‎src/libcore/str/mod.rs

+194-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ use crate::iter::{Map, Cloned, FusedIterator, TrustedLen, TrustedRandomAccess, F
1010
use crate::iter::{Flatten, FlatMap, Chain};
1111
use crate::slice::{self, SliceIndex, Split as SliceSplit};
1212
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;
1615

1716
#[unstable(feature = "str_internals", issue = "0")]
1817
mod needles;
@@ -2549,6 +2548,105 @@ impl str {
25492548
ext::rfind(self, pat)
25502549
}
25512550

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+
25522650
/// An iterator over substrings of this string slice, separated by
25532651
/// characters matched by a pattern.
25542652
///
@@ -3083,6 +3181,99 @@ impl str {
30833181
ext::rmatch_indices(self, pat)
30843182
}
30853183

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+
30863277
/// Returns a string slice with leading and trailing whitespace removed.
30873278
///
30883279
/// 'Whitespace' is defined according to the terms of the Unicode Derived

0 commit comments

Comments
 (0)
Please sign in to comment.