1919
2020use cmp;
2121use fmt;
22+ use slice:: memchr;
2223use usize;
2324
2425// Pattern
@@ -241,25 +242,66 @@ pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
241242
242243/// Associated type for `<char as Pattern<'a>>::Searcher`.
243244#[ derive( Clone , Debug ) ]
244- pub struct CharSearcher < ' a > ( & ' a str ) ;
245+ pub struct CharSearcher < ' a > {
246+ haystack : & ' a str ,
247+ // invariant: `finger` must be a valid utf8 byte index of `haystack`
248+ finger : usize ,
249+ needle : char ,
250+ // For ascii chars
251+ // invariant: must be an ASCII byte (no high bit)
252+ single_byte : Option < u8 > ,
253+ }
245254
246255unsafe impl < ' a > Searcher < ' a > for CharSearcher < ' a > {
247256 #[ inline]
248257 fn haystack ( & self ) -> & ' a str {
249- unimplemented ! ( ) ;
258+ self . haystack
250259 }
251260 #[ inline]
252261 fn next ( & mut self ) -> SearchStep {
253- unimplemented ! ( ) ;
262+ let old_finger = self . finger ;
263+ let slice = unsafe { self . haystack . get_unchecked ( old_finger..) } ;
264+ let mut iter = slice. chars ( ) ;
265+ let old_len = iter. iter . len ( ) ;
266+ if let Some ( ch) = iter. next ( ) {
267+ // add byte offset of current character
268+ // without recalculating
269+ self . finger += iter. iter . len ( ) - old_len;
270+ if ch == self . needle {
271+ SearchStep :: Match ( old_finger, self . finger )
272+ } else {
273+ SearchStep :: Reject ( old_finger, self . finger )
274+ }
275+ } else {
276+ SearchStep :: Done
277+ }
254278 }
255279 #[ inline]
256280 fn next_match ( & mut self ) -> Option < ( usize , usize ) > {
257- unimplemented ! ( ) ;
258- }
259- #[ inline]
260- fn next_reject ( & mut self ) -> Option < ( usize , usize ) > {
261- unimplemented ! ( ) ;
281+ if let Some ( byte) = self . single_byte {
282+ let old_finger = self . finger ;
283+ let slice = unsafe { self . haystack . get_unchecked ( old_finger..) } ;
284+ let bytes = slice. as_bytes ( ) ;
285+ if let Some ( index) = memchr:: memchr ( byte, bytes) {
286+ // index is the index of a valid ASCII byte,
287+ // so we can add one to it
288+ self . finger += index + 1 ;
289+ Some ( ( index, self . finger ) )
290+ } else {
291+ None
292+ }
293+ } else {
294+ loop {
295+ match self . next ( ) {
296+ SearchStep :: Match ( a, b) => break Some ( ( a, b) ) ,
297+ SearchStep :: Done => break None ,
298+ _ => continue ,
299+ }
300+ }
301+ }
262302 }
303+
304+ // let next_reject use the default implementation from the Searcher trait
263305}
264306
265307unsafe impl < ' a > ReverseSearcher < ' a > for CharSearcher < ' a > {
@@ -271,10 +313,8 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> {
271313 fn next_match_back ( & mut self ) -> Option < ( usize , usize ) > {
272314 unimplemented ! ( ) ;
273315 }
274- #[ inline]
275- fn next_reject_back ( & mut self ) -> Option < ( usize , usize ) > {
276- unimplemented ! ( ) ;
277- }
316+
317+ // let next_reject_back use the default implementation from the Searcher trait
278318}
279319
280320impl < ' a > DoubleEndedSearcher < ' a > for CharSearcher < ' a > { }
@@ -285,7 +325,19 @@ impl<'a> Pattern<'a> for char {
285325
286326 #[ inline]
287327 fn into_searcher ( self , haystack : & ' a str ) -> Self :: Searcher {
288- CharSearcher ( haystack)
328+ let single_byte = if self . len_utf8 ( ) == 1 {
329+ let mut storage = [ 0 ] ;
330+ self . encode_utf8 ( & mut storage) ;
331+ Some ( storage[ 0 ] )
332+ } else {
333+ None
334+ } ;
335+ CharSearcher {
336+ haystack,
337+ finger : 0 ,
338+ needle : self ,
339+ single_byte,
340+ }
289341 }
290342
291343 #[ inline]
0 commit comments