@@ -12,7 +12,8 @@ use std::collections::hash_map::DefaultHasher;
1212use std:: hash:: { Hash , Hasher } ;
1313
1414use super :: objint;
15- use super :: objsequence:: PySliceableSequence ;
15+ use super :: objtype;
16+ use super :: objsequence:: { PySliceableSequence , is_valid_slice_arg} ;
1617use crate :: obj:: objint:: PyInt ;
1718use num_integer:: Integer ;
1819use num_traits:: ToPrimitive ;
@@ -21,6 +22,7 @@ use super::objbytearray::{get_value as get_value_bytearray, PyByteArray};
2122use super :: objbytes:: PyBytes ;
2223use super :: objmemory:: PyMemoryView ;
2324use super :: objnone:: PyNone ;
25+ use super :: objsequence;
2426
2527#[ derive( Debug , Default , Clone ) ]
2628pub struct PyByteInner {
@@ -495,6 +497,61 @@ impl PyByteInner {
495497
496498 Ok ( vm. ctx . new_bytes ( refs) )
497499 }
500+
501+ pub fn startsendswith (
502+ & self ,
503+ arg : PyObjectRef ,
504+ start : OptionalArg < PyObjectRef > ,
505+ end : OptionalArg < PyObjectRef > ,
506+ endswith : bool , // true for endswith, false for startswith
507+ vm : & VirtualMachine ,
508+ ) -> PyResult {
509+ let suff = if objtype:: isinstance ( & arg, & vm. ctx . tuple_type ( ) ) {
510+ let mut flatten = vec ! [ ] ;
511+ for v in objsequence:: get_elements ( & arg) . to_vec ( ) {
512+ match try_as_bytes_like ( & v) {
513+ None => {
514+ return Err ( vm. new_type_error ( format ! (
515+ "a bytes-like object is required, not {}" ,
516+ & v. class( ) . name,
517+ ) ) ) ;
518+ }
519+ Some ( value) => flatten. extend ( value) ,
520+ }
521+ }
522+ flatten
523+ } else {
524+ match try_as_bytes_like ( & arg) {
525+ Some ( value) => value,
526+ None => {
527+ return Err ( vm. new_type_error ( format ! (
528+ "endswith first arg must be bytes or a tuple of bytes, not {}" ,
529+ arg
530+ ) ) ) ;
531+ }
532+ }
533+ } ;
534+
535+ if suff. is_empty ( ) {
536+ return Ok ( vm. new_bool ( true ) ) ;
537+ }
538+ let range = self . elements . get_slice_range (
539+ & is_valid_slice_arg ( start, vm) ?,
540+ & is_valid_slice_arg ( end, vm) ?,
541+ ) ;
542+
543+ if range. end - range. start < suff. len ( ) {
544+ return Ok ( vm. new_bool ( false ) ) ;
545+ }
546+
547+ let offset = if endswith {
548+ ( range. end - suff. len ( ) ) ..range. end
549+ } else {
550+ 0 ..suff. len ( )
551+ } ;
552+
553+ Ok ( vm. new_bool ( suff. as_slice ( ) == & self . elements . do_slice ( range) [ offset] ) )
554+ }
498555}
499556
500557pub fn try_as_byte ( obj : & PyObjectRef ) -> Option < Vec < u8 > > {
0 commit comments