Skip to content

Commit f865164

Browse files
committed
Fill in reverse searcher impl for char
1 parent d9dc44a commit f865164

File tree

1 file changed

+50
-6
lines changed

1 file changed

+50
-6
lines changed

src/libcore/str/pattern.rs

+50-6
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ pub unsafe trait Searcher<'a> {
128128
fn next(&mut self) -> SearchStep;
129129

130130
/// Find the next `Match` result. See `next()`
131+
///
132+
/// Unlike next(), there is no guarantee that the returned ranges
133+
/// of this and next_reject will overlap. This will return (start_match, end_match),
134+
/// where start_match is the index of where the match begins, and end_match is
135+
/// the index after the end of the match.
131136
#[inline]
132137
fn next_match(&mut self) -> Option<(usize, usize)> {
133138
loop {
@@ -139,7 +144,10 @@ pub unsafe trait Searcher<'a> {
139144
}
140145
}
141146

142-
/// Find the next `Reject` result. See `next()`
147+
/// Find the next `Reject` result. See `next()` and `next_match()`
148+
///
149+
/// Unlike next(), there is no guarantee that the returned ranges
150+
/// of this and next_match will overlap.
143151
#[inline]
144152
fn next_reject(&mut self) -> Option<(usize, usize)> {
145153
loop {
@@ -244,8 +252,9 @@ pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
244252
#[derive(Clone, Debug)]
245253
pub struct CharSearcher<'a> {
246254
haystack: &'a str,
247-
// invariant: `finger` must be a valid utf8 byte index of `haystack`
255+
// invariant: `finger`/`finger_back` must be a valid utf8 byte index of `haystack`
248256
finger: usize,
257+
finger_back: usize,
249258
needle: char,
250259
// For ascii chars
251260
// invariant: must be an ASCII byte (no high bit)
@@ -266,7 +275,7 @@ unsafe impl<'a> Searcher<'a> for CharSearcher<'a> {
266275
if let Some(ch) = iter.next() {
267276
// add byte offset of current character
268277
// without recalculating
269-
self.finger += iter.iter.len() - old_len;
278+
self.finger += old_len - iter.iter.len();
270279
if ch == self.needle {
271280
SearchStep::Match(old_finger, self.finger)
272281
} else {
@@ -286,7 +295,7 @@ unsafe impl<'a> Searcher<'a> for CharSearcher<'a> {
286295
// index is the index of a valid ASCII byte,
287296
// so we can add one to it
288297
self.finger += index + 1;
289-
Some((index, self.finger))
298+
Some((self.finger - 1, self.finger))
290299
} else {
291300
None
292301
}
@@ -307,11 +316,45 @@ unsafe impl<'a> Searcher<'a> for CharSearcher<'a> {
307316
unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> {
308317
#[inline]
309318
fn next_back(&mut self) -> SearchStep {
310-
unimplemented!();
319+
let old_finger = self.finger_back;
320+
let slice = unsafe { self.haystack.slice_unchecked(0, old_finger) };
321+
let mut iter = slice.chars();
322+
let old_len = iter.iter.len();
323+
if let Some(ch) = iter.next_back() {
324+
// subtract byte offset of current character
325+
// without recalculating
326+
self.finger_back -= old_len - iter.iter.len();
327+
if ch == self.needle {
328+
SearchStep::Match(self.finger_back, old_finger)
329+
} else {
330+
SearchStep::Reject(self.finger_back, old_finger)
331+
}
332+
} else {
333+
SearchStep::Done
334+
}
311335
}
312336
#[inline]
313337
fn next_match_back(&mut self) -> Option<(usize, usize)> {
314-
unimplemented!();
338+
if let Some(byte) = self.single_byte {
339+
let old_finger = self.finger_back;
340+
let slice = unsafe { self.haystack.slice_unchecked(0, old_finger) };
341+
let bytes = slice.as_bytes();
342+
if let Some(index) = memchr::memrchr(byte, bytes) {
343+
// index is the index of a valid ASCII byte
344+
self.finger_back = index;
345+
Some((self.finger_back, self.finger_back + 1))
346+
} else {
347+
None
348+
}
349+
} else {
350+
loop {
351+
match self.next_back() {
352+
SearchStep::Match(a, b) => break Some((a, b)),
353+
SearchStep::Done => break None,
354+
_ => continue,
355+
}
356+
}
357+
}
315358
}
316359

317360
// let next_reject_back use the default implementation from the Searcher trait
@@ -335,6 +378,7 @@ impl<'a> Pattern<'a> for char {
335378
CharSearcher {
336379
haystack,
337380
finger: 0,
381+
finger_back: haystack.len(),
338382
needle: self,
339383
single_byte,
340384
}

0 commit comments

Comments
 (0)