@@ -13,7 +13,7 @@ use super::objmemory::PyMemoryView;
13
13
use super :: objnone:: PyNoneRef ;
14
14
use super :: objsequence:: { is_valid_slice_arg, PySliceableSequence } ;
15
15
use super :: objslice:: PySliceRef ;
16
- use super :: objstr:: { self , PyString , PyStringRef } ;
16
+ use super :: objstr:: { self , adjust_indices , PyString , PyStringRef , StringRange } ;
17
17
use super :: objtuple:: PyTupleRef ;
18
18
use crate :: function:: OptionalArg ;
19
19
use crate :: pyhash;
@@ -137,34 +137,22 @@ pub struct ByteInnerFindOptions {
137
137
#[ pyarg( positional_only, optional = false ) ]
138
138
sub : Either < PyByteInner , PyIntRef > ,
139
139
#[ pyarg( positional_only, optional = true ) ]
140
- start : OptionalArg < Option < PyIntRef > > ,
140
+ start : OptionalArg < Option < isize > > ,
141
141
#[ pyarg( positional_only, optional = true ) ]
142
- end : OptionalArg < Option < PyIntRef > > ,
142
+ end : OptionalArg < Option < isize > > ,
143
143
}
144
144
145
145
impl ByteInnerFindOptions {
146
146
pub fn get_value (
147
147
self ,
148
- elements : & [ u8 ] ,
148
+ len : usize ,
149
149
vm : & VirtualMachine ,
150
- ) -> PyResult < ( Vec < u8 > , Range < usize > ) > {
150
+ ) -> PyResult < ( Vec < u8 > , std :: ops :: Range < usize > ) > {
151
151
let sub = match self . sub {
152
152
Either :: A ( v) => v. elements . to_vec ( ) ,
153
153
Either :: B ( int) => vec ! [ int. as_bigint( ) . byte_or( vm) ?] ,
154
154
} ;
155
-
156
- let start = match self . start {
157
- OptionalArg :: Present ( Some ( int) ) => Some ( int. as_bigint ( ) . clone ( ) ) ,
158
- _ => None ,
159
- } ;
160
-
161
- let end = match self . end {
162
- OptionalArg :: Present ( Some ( int) ) => Some ( int. as_bigint ( ) . clone ( ) ) ,
163
- _ => None ,
164
- } ;
165
-
166
- let range = elements. to_vec ( ) . get_slice_range ( & start, & end) ;
167
-
155
+ let range = adjust_indices ( self . start , self . end , len) ;
168
156
Ok ( ( sub, range) )
169
157
}
170
158
}
@@ -808,25 +796,18 @@ impl PyByteInner {
808
796
}
809
797
810
798
pub fn count ( & self , options : ByteInnerFindOptions , vm : & VirtualMachine ) -> PyResult < usize > {
811
- let ( sub, range) = options. get_value ( & self . elements , vm) ?;
812
-
813
- if sub. is_empty ( ) {
814
- return Ok ( self . len ( ) + 1 ) ;
799
+ let ( needle, range) = options. get_value ( self . elements . len ( ) , vm) ?;
800
+ if !range. is_normal ( ) {
801
+ return Ok ( 0 ) ;
815
802
}
816
-
817
- let mut total: usize = 0 ;
818
- let mut i_start = range. start ;
819
- let i_end = range. end ;
820
-
821
- for i in self . elements . do_slice ( range) {
822
- if i_start + sub. len ( ) <= i_end
823
- && i == sub[ 0 ]
824
- && & self . elements [ i_start..( i_start + sub. len ( ) ) ] == sub. as_slice ( )
825
- {
826
- total += 1 ;
827
- }
828
- i_start += 1 ;
803
+ if needle. is_empty ( ) {
804
+ return Ok ( range. len ( ) + 1 ) ;
829
805
}
806
+ let haystack = & self . elements [ range] ;
807
+ let total = haystack
808
+ . windows ( needle. len ( ) )
809
+ . filter ( |w| * w == needle. as_slice ( ) )
810
+ . count ( ) ;
830
811
Ok ( total)
831
812
}
832
813
@@ -884,37 +865,36 @@ impl PyByteInner {
884
865
Ok ( suff. as_slice ( ) == & self . elements . do_slice ( range) [ offset] )
885
866
}
886
867
868
+ #[ inline]
887
869
pub fn find (
888
870
& self ,
889
871
options : ByteInnerFindOptions ,
890
872
reverse : bool ,
891
873
vm : & VirtualMachine ,
892
- ) -> PyResult < isize > {
893
- let ( sub, range) = options. get_value ( & self . elements , vm) ?;
894
- // not allowed for this method
895
- if range. end < range. start {
896
- return Ok ( -1isize ) ;
874
+ ) -> PyResult < Option < usize > > {
875
+ let ( needle, range) = options. get_value ( self . elements . len ( ) , vm) ?;
876
+ if !range. is_normal ( ) {
877
+ return Ok ( None ) ;
897
878
}
898
-
899
- let start = range. start ;
900
- let end = range. end ;
901
-
879
+ if needle. is_empty ( ) {
880
+ return Ok ( Some ( if reverse { range. end } else { range. start } ) ) ;
881
+ }
882
+ let haystack = & self . elements [ range. clone ( ) ] ;
883
+ let windows = haystack. windows ( needle. len ( ) ) ;
902
884
if reverse {
903
- let slice = self . elements . do_slice_reverse ( range) ;
904
- for ( n, _) in slice. iter ( ) . enumerate ( ) {
905
- if n + sub. len ( ) <= slice. len ( ) && & slice[ n..n + sub. len ( ) ] == sub. as_slice ( ) {
906
- return Ok ( ( end - n - 1 ) as isize ) ;
885
+ for ( i, w) in windows. rev ( ) . enumerate ( ) {
886
+ if w == needle. as_slice ( ) {
887
+ return Ok ( Some ( range. end - i - needle. len ( ) ) ) ;
907
888
}
908
889
}
909
890
} else {
910
- let slice = self . elements . do_slice ( range) ;
911
- for ( n, _) in slice. iter ( ) . enumerate ( ) {
912
- if n + sub. len ( ) <= slice. len ( ) && & slice[ n..n + sub. len ( ) ] == sub. as_slice ( ) {
913
- return Ok ( ( start + n) as isize ) ;
891
+ for ( i, w) in windows. enumerate ( ) {
892
+ if w == needle. as_slice ( ) {
893
+ return Ok ( Some ( range. start + i) ) ;
914
894
}
915
895
}
916
- } ;
917
- Ok ( - 1isize )
896
+ }
897
+ Ok ( None )
918
898
}
919
899
920
900
pub fn maketrans ( from : PyByteInner , to : PyByteInner , vm : & VirtualMachine ) -> PyResult {
0 commit comments