std: Update MatchIndices to return a subslice
This commit updates the `MatchIndices` and `RMatchIndices` iterators to follow the same pattern as the `chars` and `char_indices` iterators. The `matches` iterator currently yield `&str` elements, so the `MatchIndices` iterator now yields the index of the match as well as the `&str` that matched (instead of start/end indexes). cc #27743
This commit is contained in:
parent
8fe79bdfda
commit
d5f2d3b177
@ -1157,25 +1157,21 @@ impl str {
|
||||
core_str::StrExt::rmatches(self, pat)
|
||||
}
|
||||
|
||||
/// An iterator over the start and end indices of the disjoint matches
|
||||
/// of a pattern within `self`.
|
||||
/// An iterator over the disjoint matches of a pattern within `self` as well
|
||||
/// as the index that the match starts at.
|
||||
///
|
||||
/// For matches of `pat` within `self` that overlap, only the indices
|
||||
/// corresponding to the first
|
||||
/// match are returned.
|
||||
/// corresponding to the first match are returned.
|
||||
///
|
||||
/// The pattern can be a simple `&str`, `char`, or a closure that
|
||||
/// determines if a character matches.
|
||||
/// Additional libraries might provide more complex patterns like
|
||||
/// regular expressions.
|
||||
/// The pattern can be a simple `&str`, `char`, or a closure that determines
|
||||
/// if a character matches. Additional libraries might provide more complex
|
||||
/// patterns like regular expressions.
|
||||
///
|
||||
/// # Iterator behavior
|
||||
///
|
||||
/// The returned iterator will be double ended if the pattern allows a
|
||||
/// reverse search
|
||||
/// and forward/reverse search yields the same elements. This is true for,
|
||||
/// eg, `char` but not
|
||||
/// for `&str`.
|
||||
/// reverse search and forward/reverse search yields the same elements. This
|
||||
/// is true for, eg, `char` but not for `&str`.
|
||||
///
|
||||
/// If the pattern allows a reverse search but its results might differ
|
||||
/// from a forward search, `rmatch_indices()` can be used.
|
||||
@ -1185,42 +1181,36 @@ impl str {
|
||||
/// ```
|
||||
/// #![feature(str_match_indices)]
|
||||
///
|
||||
/// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect();
|
||||
/// assert_eq!(v, [(0, 3), (6, 9), (12, 15)]);
|
||||
/// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
|
||||
/// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
|
||||
///
|
||||
/// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect();
|
||||
/// assert_eq!(v, [(1, 4), (4, 7)]);
|
||||
/// let v: Vec<_> = "1abcabc2".match_indices("abc").collect();
|
||||
/// assert_eq!(v, [(1, "abc"), (4, "abc")]);
|
||||
///
|
||||
/// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
|
||||
/// assert_eq!(v, [(0, 3)]); // only the first `aba`
|
||||
/// let v: Vec<_> = "ababa".match_indices("aba").collect();
|
||||
/// assert_eq!(v, [(0, "aba")]); // only the first `aba`
|
||||
/// ```
|
||||
#[unstable(feature = "str_match_indices",
|
||||
reason = "might have its iterator type changed",
|
||||
issue = "27743")]
|
||||
// NB: Right now MatchIndices yields `(usize, usize)`, but it would
|
||||
// be more consistent with `matches` and `char_indices` to return `(usize, &str)`
|
||||
pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
|
||||
core_str::StrExt::match_indices(self, pat)
|
||||
}
|
||||
|
||||
/// An iterator over the start and end indices of the disjoint matches of
|
||||
/// a pattern within
|
||||
/// `self`, yielded in reverse order.
|
||||
/// An iterator over the disjoint matches of a pattern within `self`,
|
||||
/// yielded in reverse order along with the index of the match.
|
||||
///
|
||||
/// For matches of `pat` within `self` that overlap, only the indices
|
||||
/// corresponding to the last
|
||||
/// match are returned.
|
||||
/// corresponding to the last match are returned.
|
||||
///
|
||||
/// The pattern can be a simple `&str`, `char`, or a closure that
|
||||
/// determines if a character matches.
|
||||
/// Additional libraries might provide more complex patterns like
|
||||
/// regular expressions.
|
||||
/// The pattern can be a simple `&str`, `char`, or a closure that determines
|
||||
/// if a character matches. Additional libraries might provide more complex
|
||||
/// patterns like regular expressions.
|
||||
///
|
||||
/// # Iterator behavior
|
||||
///
|
||||
/// The returned iterator requires that the pattern supports a
|
||||
/// reverse search,
|
||||
/// and it will be double ended if a forward/reverse search yields
|
||||
/// The returned iterator requires that the pattern supports a reverse
|
||||
/// search, and it will be double ended if a forward/reverse search yields
|
||||
/// the same elements.
|
||||
///
|
||||
/// For iterating from the front, `match_indices()` can be used.
|
||||
@ -1230,20 +1220,18 @@ impl str {
|
||||
/// ```
|
||||
/// #![feature(str_match_indices)]
|
||||
///
|
||||
/// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
|
||||
/// assert_eq!(v, [(12, 15), (6, 9), (0, 3)]);
|
||||
/// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
|
||||
/// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
|
||||
///
|
||||
/// let v: Vec<(usize, usize)> = "1abcabc2".rmatch_indices("abc").collect();
|
||||
/// assert_eq!(v, [(4, 7), (1, 4)]);
|
||||
/// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect();
|
||||
/// assert_eq!(v, [(4, "abc"), (1, "abc")]);
|
||||
///
|
||||
/// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect();
|
||||
/// assert_eq!(v, [(2, 5)]); // only the last `aba`
|
||||
/// let v: Vec<_> = "ababa".rmatch_indices("aba").collect();
|
||||
/// assert_eq!(v, [(2, "aba")]); // only the last `aba`
|
||||
/// ```
|
||||
#[unstable(feature = "str_match_indices",
|
||||
reason = "might have its iterator type changed",
|
||||
issue = "27743")]
|
||||
// NB: Right now RMatchIndices yields `(usize, usize)`, but it would
|
||||
// be more consistent with `rmatches` and `char_indices` to return `(usize, &str)`
|
||||
pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
|
||||
where P::Searcher: ReverseSearcher<'a>
|
||||
{
|
||||
@ -1416,10 +1404,10 @@ impl str {
|
||||
pub fn replace(&self, from: &str, to: &str) -> String {
|
||||
let mut result = String::new();
|
||||
let mut last_end = 0;
|
||||
for (start, end) in self.match_indices(from) {
|
||||
for (start, part) in self.match_indices(from) {
|
||||
result.push_str(unsafe { self.slice_unchecked(last_end, start) });
|
||||
result.push_str(to);
|
||||
last_end = end;
|
||||
last_end = start + part.len();
|
||||
}
|
||||
result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) });
|
||||
result
|
||||
|
@ -1047,7 +1047,7 @@ fn test_pattern_deref_forward() {
|
||||
fn test_empty_match_indices() {
|
||||
let data = "aä中!";
|
||||
let vec: Vec<_> = data.match_indices("").collect();
|
||||
assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
|
||||
assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1477,7 +1477,7 @@ generate_iterator_test! {
|
||||
|
||||
generate_iterator_test! {
|
||||
double_ended_match_indices {
|
||||
("a1b2c3", char::is_numeric) -> [(1, 2), (3, 4), (5, 6)];
|
||||
("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
|
||||
}
|
||||
with str::match_indices, str::rmatch_indices;
|
||||
}
|
||||
|
@ -729,15 +729,19 @@ struct MatchIndicesInternal<'a, P: Pattern<'a>>(P::Searcher);
|
||||
|
||||
impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(usize, usize)> {
|
||||
self.0.next_match()
|
||||
fn next(&mut self) -> Option<(usize, &'a str)> {
|
||||
self.0.next_match().map(|(start, end)| unsafe {
|
||||
(start, self.0.haystack().slice_unchecked(start, end))
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<(usize, usize)>
|
||||
fn next_back(&mut self) -> Option<(usize, &'a str)>
|
||||
where P::Searcher: ReverseSearcher<'a>
|
||||
{
|
||||
self.0.next_match_back()
|
||||
self.0.next_match_back().map(|(start, end)| unsafe {
|
||||
(start, self.0.haystack().slice_unchecked(start, end))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -753,7 +757,7 @@ generate_pattern_iterators! {
|
||||
reason = "type may be removed or have its iterator impl changed",
|
||||
issue = "27743")]
|
||||
internal:
|
||||
MatchIndicesInternal yielding ((usize, usize));
|
||||
MatchIndicesInternal yielding ((usize, &'a str));
|
||||
delegate double ended;
|
||||
}
|
||||
|
||||
|
@ -331,10 +331,10 @@ fn split_msg_into_multilines(msg: &str) -> Option<String> {
|
||||
let first = msg.match_indices("expected").filter(|s| {
|
||||
s.0 > 0 && (msg.char_at_reverse(s.0) == ' ' ||
|
||||
msg.char_at_reverse(s.0) == '(')
|
||||
}).map(|(a, b)| (a - 1, b));
|
||||
}).map(|(a, b)| (a - 1, a + b.len()));
|
||||
let second = msg.match_indices("found").filter(|s| {
|
||||
msg.char_at_reverse(s.0) == ' '
|
||||
}).map(|(a, b)| (a - 1, b));
|
||||
}).map(|(a, b)| (a - 1, a + b.len()));
|
||||
|
||||
let mut new_msg = String::new();
|
||||
let mut head = 0;
|
||||
|
@ -59,5 +59,5 @@ fn match_indices<'a, M, T: IntoMatcher<'a, M>>(s: &'a str, from: T) -> MatchIndi
|
||||
fn main() {
|
||||
let s = "abcbdef";
|
||||
match_indices(s, |c: char| c == 'b')
|
||||
.collect::<Vec<(usize, usize)>>();
|
||||
.collect::<Vec<_>>();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user