20
20
use prelude:: v1:: * ;
21
21
22
22
use cmp;
23
+ use slice;
23
24
use usize;
24
25
25
26
// Pattern
@@ -545,6 +546,7 @@ pub struct StrSearcher<'a, 'b> {
545
546
#[ derive( Clone , Debug ) ]
546
547
enum StrSearcherImpl {
547
548
Empty ( EmptyNeedle ) ,
549
+ Single ( SingleByte ) ,
548
550
TwoWay ( TwoWaySearcher ) ,
549
551
}
550
552
@@ -556,6 +558,15 @@ struct EmptyNeedle {
556
558
is_match_bw : bool ,
557
559
}
558
560
561
+ #[ derive( Clone , Debug ) ]
562
+ struct SingleByte {
563
+ byte : u8 ,
564
+ position : usize ,
565
+ end : usize ,
566
+ is_match_fw : bool ,
567
+ is_match_bw : bool ,
568
+ }
569
+
559
570
impl < ' a , ' b > StrSearcher < ' a , ' b > {
560
571
fn new ( haystack : & ' a str , needle : & ' b str ) -> StrSearcher < ' a , ' b > {
561
572
if needle. is_empty ( ) {
@@ -569,6 +580,19 @@ impl<'a, 'b> StrSearcher<'a, 'b> {
569
580
is_match_bw : true ,
570
581
} ) ,
571
582
}
583
+ } else if needle. len ( ) == 1 {
584
+ // Note: A single byte needle must have a single ASCII byte.
585
+ StrSearcher {
586
+ haystack : haystack,
587
+ needle : needle,
588
+ searcher : StrSearcherImpl :: Single ( SingleByte {
589
+ byte : needle. as_bytes ( ) [ 0 ] ,
590
+ position : 0 ,
591
+ end : haystack. len ( ) ,
592
+ is_match_fw : false ,
593
+ is_match_bw : false ,
594
+ } ) ,
595
+ }
572
596
} else {
573
597
StrSearcher {
574
598
haystack : haystack,
@@ -601,6 +625,24 @@ unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> {
601
625
}
602
626
}
603
627
}
628
+ StrSearcherImpl :: Single ( ref mut searcher) => {
629
+ let pos = searcher. position ;
630
+ if searcher. is_match_fw {
631
+ searcher. is_match_fw = false ;
632
+ searcher. position += 1 ;
633
+ SearchStep :: Match ( pos, pos + 1 )
634
+ } else {
635
+ match slice:: bytes:: find_byte ( searcher. byte ,
636
+ & self . haystack . as_bytes ( ) [ pos..] ) {
637
+ None => SearchStep :: Done ,
638
+ Some ( index) => {
639
+ searcher. position += index;
640
+ searcher. is_match_fw = true ;
641
+ SearchStep :: Reject ( pos, searcher. position )
642
+ }
643
+ }
644
+ }
645
+ }
604
646
StrSearcherImpl :: TwoWay ( ref mut searcher) => {
605
647
// TwoWaySearcher produces valid *Match* indices that split at char boundaries
606
648
// as long as it does correct matching and that haystack and needle are
@@ -641,6 +683,18 @@ unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> {
641
683
}
642
684
}
643
685
}
686
+ StrSearcherImpl :: Single ( ref mut searcher) => {
687
+ let pos = searcher. position ;
688
+ searcher. is_match_fw = false ;
689
+ match slice:: bytes:: find_byte ( searcher. byte ,
690
+ & self . haystack . as_bytes ( ) [ pos..] ) {
691
+ None => None ,
692
+ Some ( index) => {
693
+ searcher. position += index;
694
+ Some ( ( index, index + 1 ) )
695
+ }
696
+ }
697
+ }
644
698
StrSearcherImpl :: TwoWay ( ref mut searcher) => {
645
699
let is_long = searcher. memory == usize:: MAX ;
646
700
// write out `true` and `false` cases to encourage the compiler
@@ -676,6 +730,24 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b> {
676
730
}
677
731
}
678
732
}
733
+ StrSearcherImpl :: Single ( ref mut searcher) => {
734
+ let end = searcher. position ;
735
+ if searcher. is_match_bw {
736
+ searcher. is_match_bw = false ;
737
+ searcher. end -= 1 ;
738
+ SearchStep :: Match ( end - 1 , end)
739
+ } else {
740
+ match slice:: bytes:: rfind_byte ( searcher. byte ,
741
+ & self . haystack . as_bytes ( ) [ ..end] ) {
742
+ None => SearchStep :: Done ,
743
+ Some ( index) => {
744
+ searcher. end = index + 1 ;
745
+ searcher. is_match_bw = true ;
746
+ SearchStep :: Reject ( index, end)
747
+ }
748
+ }
749
+ }
750
+ }
679
751
StrSearcherImpl :: TwoWay ( ref mut searcher) => {
680
752
if searcher. end == 0 {
681
753
return SearchStep :: Done ;
@@ -711,6 +783,18 @@ unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b> {
711
783
}
712
784
}
713
785
}
786
+ StrSearcherImpl :: Single ( ref mut searcher) => {
787
+ let end = searcher. position ;
788
+ searcher. is_match_bw = false ;
789
+ match slice:: bytes:: rfind_byte ( searcher. byte ,
790
+ & self . haystack . as_bytes ( ) [ ..end] ) {
791
+ None => None ,
792
+ Some ( index) => {
793
+ searcher. end = index;
794
+ Some ( ( index, index + 1 ) )
795
+ }
796
+ }
797
+ }
714
798
StrSearcherImpl :: TwoWay ( ref mut searcher) => {
715
799
let is_long = searcher. memory == usize:: MAX ;
716
800
// write out `true` and `false`, like `next_match`
0 commit comments