@@ -7,12 +7,12 @@ use crate::{
77 anystr:: { self , adjust_indices, AnyStr , AnyStrContainer , AnyStrWrapper } ,
88 format:: { FormatSpec , FormatString , FromTemplate } ,
99 function:: { ArgIterable , FuncArgs , IntoPyException , IntoPyObject , OptionalArg , OptionalOption } ,
10- protocol:: { PyIterReturn , PyMappingMethods } ,
10+ protocol:: { PyIterReturn , PyMappingMethods , PySequenceMethods } ,
1111 sequence:: SequenceOp ,
1212 sliceable:: SliceableSequenceOp ,
1313 types:: {
14- AsMapping , Comparable , Constructor , Hashable , IterNext , IterNextIterable , Iterable ,
15- PyComparisonOp , Unconstructible ,
14+ AsMapping , AsSequence , Comparable , Constructor , Hashable , IterNext , IterNextIterable ,
15+ Iterable , PyComparisonOp , Unconstructible ,
1616 } ,
1717 utils:: Either ,
1818 IdProtocol , PyClassDef , PyClassImpl , PyComparisonValue , PyContext , PyObject , PyObjectRef ,
@@ -375,7 +375,7 @@ impl PyStr {
375375
376376#[ pyimpl(
377377 flags( BASETYPE ) ,
378- with( AsMapping , Hashable , Comparable , Iterable , Constructor )
378+ with( AsMapping , AsSequence , Hashable , Comparable , Iterable , Constructor )
379379) ]
380380impl PyStr {
381381 #[ pymethod( magic) ]
@@ -404,9 +404,20 @@ impl PyStr {
404404 !self . bytes . is_empty ( )
405405 }
406406
407+ fn _contains ( & self , needle : & PyObject , vm : & VirtualMachine ) -> PyResult < bool > {
408+ if let Some ( needle) = needle. payload :: < Self > ( ) {
409+ Ok ( self . as_str ( ) . contains ( needle. as_str ( ) ) )
410+ } else {
411+ Err ( vm. new_type_error ( format ! (
412+ "'in <string>' requires string as left operand, not {}" ,
413+ needle. class( ) . name( )
414+ ) ) )
415+ }
416+ }
417+
407418 #[ pymethod( magic) ]
408- fn contains ( & self , needle : PyStrRef ) -> bool {
409- self . as_str ( ) . contains ( needle. as_str ( ) )
419+ fn contains ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> PyResult < bool > {
420+ self . _contains ( & needle, vm )
410421 }
411422
412423 #[ pymethod( magic) ]
@@ -1276,6 +1287,36 @@ impl PyStr {
12761287 } ;
12771288}
12781289
1290+ impl AsSequence for PyStr {
1291+ fn as_sequence (
1292+ _zelf : & PyObjectView < Self > ,
1293+ _vm : & VirtualMachine ,
1294+ ) -> std:: borrow:: Cow < ' static , PySequenceMethods > {
1295+ std:: borrow:: Cow :: Borrowed ( & Self :: SEQUENCE_METHDOS )
1296+ }
1297+ }
1298+
1299+ impl PyStr {
1300+ const SEQUENCE_METHDOS : PySequenceMethods = PySequenceMethods {
1301+ length : Some ( |seq, _vm| Ok ( seq. obj_as :: < Self > ( ) . len ( ) ) ) ,
1302+ concat : Some ( |seq, other, vm| {
1303+ let zelf = seq. obj_as :: < Self > ( ) ;
1304+ Self :: add ( zelf. to_owned ( ) , other. to_owned ( ) , vm)
1305+ } ) ,
1306+ repeat : Some ( |seq, n, vm| {
1307+ let zelf = seq. obj_as :: < Self > ( ) ;
1308+ Self :: mul ( zelf. to_owned ( ) , n as isize , vm) . map ( |x| x. into ( ) )
1309+ } ) ,
1310+ item : Some ( |seq, i, vm| {
1311+ let zelf = seq. obj_as :: < Self > ( ) ;
1312+ zelf. get_item_by_index ( vm, i)
1313+ . map ( |x| zelf. new_substr ( x. to_string ( ) ) . into_ref ( vm) . into ( ) )
1314+ } ) ,
1315+ contains : Some ( |seq, needle, vm| seq. obj_as :: < Self > ( ) . _contains ( needle, vm) ) ,
1316+ ..* PySequenceMethods :: not_implemented ( )
1317+ } ;
1318+ }
1319+
12791320#[ derive( FromArgs ) ]
12801321struct EncodeArgs {
12811322 #[ pyarg( any, default ) ]
0 commit comments