@@ -13,7 +13,7 @@ use super::objmemory::PyMemoryView;
1313use super :: objnone:: PyNoneRef ;
1414use super :: objsequence:: { is_valid_slice_arg, PySliceableSequence } ;
1515use super :: objslice:: PySliceRef ;
16- use super :: objstr:: { self , PyString , PyStringRef } ;
16+ use super :: objstr:: { self , adjust_indices , PyString , PyStringRef , StringRange } ;
1717use super :: objtuple:: PyTupleRef ;
1818use crate :: function:: OptionalArg ;
1919use crate :: pyhash;
@@ -137,34 +137,22 @@ pub struct ByteInnerFindOptions {
137137 #[ pyarg( positional_only, optional = false ) ]
138138 sub : Either < PyByteInner , PyIntRef > ,
139139 #[ pyarg( positional_only, optional = true ) ]
140- start : OptionalArg < Option < PyIntRef > > ,
140+ start : OptionalArg < Option < isize > > ,
141141 #[ pyarg( positional_only, optional = true ) ]
142- end : OptionalArg < Option < PyIntRef > > ,
142+ end : OptionalArg < Option < isize > > ,
143143}
144144
145145impl ByteInnerFindOptions {
146146 pub fn get_value (
147147 self ,
148- elements : & [ u8 ] ,
148+ len : usize ,
149149 vm : & VirtualMachine ,
150- ) -> PyResult < ( Vec < u8 > , Range < usize > ) > {
150+ ) -> PyResult < ( Vec < u8 > , std :: ops :: Range < usize > ) > {
151151 let sub = match self . sub {
152152 Either :: A ( v) => v. elements . to_vec ( ) ,
153153 Either :: B ( int) => vec ! [ int. as_bigint( ) . byte_or( vm) ?] ,
154154 } ;
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) ;
168156 Ok ( ( sub, range) )
169157 }
170158}
@@ -808,25 +796,18 @@ impl PyByteInner {
808796 }
809797
810798 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 ) ;
815802 }
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 ) ;
829805 }
806+ let haystack = & self . elements [ range] ;
807+ let total = haystack
808+ . windows ( needle. len ( ) )
809+ . filter ( |w| * w == needle. as_slice ( ) )
810+ . count ( ) ;
830811 Ok ( total)
831812 }
832813
@@ -884,37 +865,36 @@ impl PyByteInner {
884865 Ok ( suff. as_slice ( ) == & self . elements . do_slice ( range) [ offset] )
885866 }
886867
868+ #[ inline]
887869 pub fn find (
888870 & self ,
889871 options : ByteInnerFindOptions ,
890872 reverse : bool ,
891873 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 ) ;
897878 }
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 ( ) ) ;
902884 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 ( ) ) ) ;
907888 }
908889 }
909890 } 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) ) ;
914894 }
915895 }
916- } ;
917- Ok ( - 1isize )
896+ }
897+ Ok ( None )
918898 }
919899
920900 pub fn maketrans ( from : PyByteInner , to : PyByteInner , vm : & VirtualMachine ) -> PyResult {
0 commit comments