Skip to content

Commit 54f7b1d

Browse files
committed
Auto merge of #28632 - alexcrichton:update-match-indices, r=Kimundi
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
2 parents c9c7908 + d5f2d3b commit 54f7b1d

File tree

5 files changed

+44
-52
lines changed

5 files changed

+44
-52
lines changed

src/libcollections/str.rs

+30-42
Original file line numberDiff line numberDiff line change
@@ -1157,25 +1157,21 @@ impl str {
11571157
core_str::StrExt::rmatches(self, pat)
11581158
}
11591159

1160-
/// An iterator over the start and end indices of the disjoint matches
1161-
/// of a pattern within `self`.
1160+
/// An iterator over the disjoint matches of a pattern within `self` as well
1161+
/// as the index that the match starts at.
11621162
///
11631163
/// For matches of `pat` within `self` that overlap, only the indices
1164-
/// corresponding to the first
1165-
/// match are returned.
1164+
/// corresponding to the first match are returned.
11661165
///
1167-
/// The pattern can be a simple `&str`, `char`, or a closure that
1168-
/// determines if a character matches.
1169-
/// Additional libraries might provide more complex patterns like
1170-
/// regular expressions.
1166+
/// The pattern can be a simple `&str`, `char`, or a closure that determines
1167+
/// if a character matches. Additional libraries might provide more complex
1168+
/// patterns like regular expressions.
11711169
///
11721170
/// # Iterator behavior
11731171
///
11741172
/// The returned iterator will be double ended if the pattern allows a
1175-
/// reverse search
1176-
/// and forward/reverse search yields the same elements. This is true for,
1177-
/// eg, `char` but not
1178-
/// for `&str`.
1173+
/// reverse search and forward/reverse search yields the same elements. This
1174+
/// is true for, eg, `char` but not for `&str`.
11791175
///
11801176
/// If the pattern allows a reverse search but its results might differ
11811177
/// from a forward search, `rmatch_indices()` can be used.
@@ -1185,42 +1181,36 @@ impl str {
11851181
/// ```
11861182
/// #![feature(str_match_indices)]
11871183
///
1188-
/// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect();
1189-
/// assert_eq!(v, [(0, 3), (6, 9), (12, 15)]);
1184+
/// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
1185+
/// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
11901186
///
1191-
/// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect();
1192-
/// assert_eq!(v, [(1, 4), (4, 7)]);
1187+
/// let v: Vec<_> = "1abcabc2".match_indices("abc").collect();
1188+
/// assert_eq!(v, [(1, "abc"), (4, "abc")]);
11931189
///
1194-
/// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
1195-
/// assert_eq!(v, [(0, 3)]); // only the first `aba`
1190+
/// let v: Vec<_> = "ababa".match_indices("aba").collect();
1191+
/// assert_eq!(v, [(0, "aba")]); // only the first `aba`
11961192
/// ```
11971193
#[unstable(feature = "str_match_indices",
11981194
reason = "might have its iterator type changed",
11991195
issue = "27743")]
1200-
// NB: Right now MatchIndices yields `(usize, usize)`, but it would
1201-
// be more consistent with `matches` and `char_indices` to return `(usize, &str)`
12021196
pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
12031197
core_str::StrExt::match_indices(self, pat)
12041198
}
12051199

1206-
/// An iterator over the start and end indices of the disjoint matches of
1207-
/// a pattern within
1208-
/// `self`, yielded in reverse order.
1200+
/// An iterator over the disjoint matches of a pattern within `self`,
1201+
/// yielded in reverse order along with the index of the match.
12091202
///
12101203
/// For matches of `pat` within `self` that overlap, only the indices
1211-
/// corresponding to the last
1212-
/// match are returned.
1204+
/// corresponding to the last match are returned.
12131205
///
1214-
/// The pattern can be a simple `&str`, `char`, or a closure that
1215-
/// determines if a character matches.
1216-
/// Additional libraries might provide more complex patterns like
1217-
/// regular expressions.
1206+
/// The pattern can be a simple `&str`, `char`, or a closure that determines
1207+
/// if a character matches. Additional libraries might provide more complex
1208+
/// patterns like regular expressions.
12181209
///
12191210
/// # Iterator behavior
12201211
///
1221-
/// The returned iterator requires that the pattern supports a
1222-
/// reverse search,
1223-
/// and it will be double ended if a forward/reverse search yields
1212+
/// The returned iterator requires that the pattern supports a reverse
1213+
/// search, and it will be double ended if a forward/reverse search yields
12241214
/// the same elements.
12251215
///
12261216
/// For iterating from the front, `match_indices()` can be used.
@@ -1230,20 +1220,18 @@ impl str {
12301220
/// ```
12311221
/// #![feature(str_match_indices)]
12321222
///
1233-
/// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
1234-
/// assert_eq!(v, [(12, 15), (6, 9), (0, 3)]);
1223+
/// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
1224+
/// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
12351225
///
1236-
/// let v: Vec<(usize, usize)> = "1abcabc2".rmatch_indices("abc").collect();
1237-
/// assert_eq!(v, [(4, 7), (1, 4)]);
1226+
/// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect();
1227+
/// assert_eq!(v, [(4, "abc"), (1, "abc")]);
12381228
///
1239-
/// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect();
1240-
/// assert_eq!(v, [(2, 5)]); // only the last `aba`
1229+
/// let v: Vec<_> = "ababa".rmatch_indices("aba").collect();
1230+
/// assert_eq!(v, [(2, "aba")]); // only the last `aba`
12411231
/// ```
12421232
#[unstable(feature = "str_match_indices",
12431233
reason = "might have its iterator type changed",
12441234
issue = "27743")]
1245-
// NB: Right now RMatchIndices yields `(usize, usize)`, but it would
1246-
// be more consistent with `rmatches` and `char_indices` to return `(usize, &str)`
12471235
pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
12481236
where P::Searcher: ReverseSearcher<'a>
12491237
{
@@ -1416,10 +1404,10 @@ impl str {
14161404
pub fn replace(&self, from: &str, to: &str) -> String {
14171405
let mut result = String::new();
14181406
let mut last_end = 0;
1419-
for (start, end) in self.match_indices(from) {
1407+
for (start, part) in self.match_indices(from) {
14201408
result.push_str(unsafe { self.slice_unchecked(last_end, start) });
14211409
result.push_str(to);
1422-
last_end = end;
1410+
last_end = start + part.len();
14231411
}
14241412
result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) });
14251413
result

src/libcollectionstest/str.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ fn test_pattern_deref_forward() {
10471047
fn test_empty_match_indices() {
10481048
let data = "aä中!";
10491049
let vec: Vec<_> = data.match_indices("").collect();
1050-
assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
1050+
assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
10511051
}
10521052

10531053
#[test]
@@ -1477,7 +1477,7 @@ generate_iterator_test! {
14771477

14781478
generate_iterator_test! {
14791479
double_ended_match_indices {
1480-
("a1b2c3", char::is_numeric) -> [(1, 2), (3, 4), (5, 6)];
1480+
("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
14811481
}
14821482
with str::match_indices, str::rmatch_indices;
14831483
}

src/libcore/str/mod.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -729,15 +729,19 @@ struct MatchIndicesInternal<'a, P: Pattern<'a>>(P::Searcher);
729729

730730
impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
731731
#[inline]
732-
fn next(&mut self) -> Option<(usize, usize)> {
733-
self.0.next_match()
732+
fn next(&mut self) -> Option<(usize, &'a str)> {
733+
self.0.next_match().map(|(start, end)| unsafe {
734+
(start, self.0.haystack().slice_unchecked(start, end))
735+
})
734736
}
735737

736738
#[inline]
737-
fn next_back(&mut self) -> Option<(usize, usize)>
739+
fn next_back(&mut self) -> Option<(usize, &'a str)>
738740
where P::Searcher: ReverseSearcher<'a>
739741
{
740-
self.0.next_match_back()
742+
self.0.next_match_back().map(|(start, end)| unsafe {
743+
(start, self.0.haystack().slice_unchecked(start, end))
744+
})
741745
}
742746
}
743747

@@ -753,7 +757,7 @@ generate_pattern_iterators! {
753757
reason = "type may be removed or have its iterator impl changed",
754758
issue = "27743")]
755759
internal:
756-
MatchIndicesInternal yielding ((usize, usize));
760+
MatchIndicesInternal yielding ((usize, &'a str));
757761
delegate double ended;
758762
}
759763

src/librustc/session/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,10 @@ fn split_msg_into_multilines(msg: &str) -> Option<String> {
331331
let first = msg.match_indices("expected").filter(|s| {
332332
s.0 > 0 && (msg.char_at_reverse(s.0) == ' ' ||
333333
msg.char_at_reverse(s.0) == '(')
334-
}).map(|(a, b)| (a - 1, b));
334+
}).map(|(a, b)| (a - 1, a + b.len()));
335335
let second = msg.match_indices("found").filter(|s| {
336336
msg.char_at_reverse(s.0) == ' '
337-
}).map(|(a, b)| (a - 1, b));
337+
}).map(|(a, b)| (a - 1, a + b.len()));
338338

339339
let mut new_msg = String::new();
340340
let mut head = 0;

src/test/run-pass/issue-14919.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,5 @@ fn match_indices<'a, M, T: IntoMatcher<'a, M>>(s: &'a str, from: T) -> MatchIndi
5959
fn main() {
6060
let s = "abcbdef";
6161
match_indices(s, |c: char| c == 'b')
62-
.collect::<Vec<(usize, usize)>>();
62+
.collect::<Vec<_>>();
6363
}

0 commit comments

Comments
 (0)