@@ -32,15 +32,15 @@ enum SearchType {
32
32
// and place in vm.rs for all sequences to be able to use it.
33
33
#[ inline]
34
34
fn iter_search (
35
- obj : PyObjectRef ,
36
- item : PyObjectRef ,
35
+ obj : & PyObject ,
36
+ item : & PyObject ,
37
37
flag : SearchType ,
38
38
vm : & VirtualMachine ,
39
39
) -> PyResult < usize > {
40
40
let mut count = 0 ;
41
41
let iter = obj. get_iter ( vm) ?;
42
42
for element in iter. iter_without_hint :: < PyObjectRef > ( vm) ? {
43
- if vm. bool_eq ( & item, & * element?) ? {
43
+ if vm. bool_eq ( item, & * element?) ? {
44
44
match flag {
45
45
SearchType :: Index => return Ok ( count) ,
46
46
SearchType :: Contains => return Ok ( 1 ) ,
@@ -53,8 +53,7 @@ fn iter_search(
53
53
SearchType :: Contains => Ok ( 0 ) ,
54
54
SearchType :: Index => Err ( vm. new_value_error ( format ! (
55
55
"{} not in range" ,
56
- & item
57
- . repr( vm)
56
+ item. repr( vm)
58
57
. map( |v| v. as_str( ) . to_owned( ) )
59
58
. unwrap_or_else( |_| "value" . to_owned( ) )
60
59
) ) ) ,
@@ -174,7 +173,15 @@ pub fn init(context: &Context) {
174
173
PyRangeIterator :: extend_class ( context, context. types . range_iterator_type ) ;
175
174
}
176
175
177
- #[ pyclass( with( AsMapping , AsSequence , Hashable , Comparable , Iterable , Representable ) ) ]
176
+ #[ pyclass( with(
177
+ Py ,
178
+ AsMapping ,
179
+ AsSequence ,
180
+ Hashable ,
181
+ Comparable ,
182
+ Iterable ,
183
+ Representable
184
+ ) ) ]
178
185
impl PyRange {
179
186
fn new ( cls : PyTypeRef , stop : ArgIndex , vm : & VirtualMachine ) -> PyResult < PyRef < Self > > {
180
187
PyRange {
@@ -265,26 +272,6 @@ impl PyRange {
265
272
!self . is_empty ( )
266
273
}
267
274
268
- #[ pymethod( magic) ]
269
- fn contains ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> bool {
270
- // Only accept ints, not subclasses.
271
- if let Some ( int) = needle. payload_if_exact :: < PyInt > ( vm) {
272
- match self . offset ( int. as_bigint ( ) ) {
273
- Some ( ref offset) => offset. is_multiple_of ( self . step . as_bigint ( ) ) ,
274
- None => false ,
275
- }
276
- } else {
277
- iter_search (
278
- self . clone ( ) . into_pyobject ( vm) ,
279
- needle,
280
- SearchType :: Contains ,
281
- vm,
282
- )
283
- . unwrap_or ( 0 )
284
- != 0
285
- }
286
- }
287
-
288
275
#[ pymethod( magic) ]
289
276
fn reduce ( & self , vm : & VirtualMachine ) -> ( PyTypeRef , PyTupleRef ) {
290
277
let range_parameters: Vec < PyObjectRef > = [ & self . start , & self . stop , & self . step ]
@@ -295,43 +282,6 @@ impl PyRange {
295
282
( vm. ctx . types . range_type . to_owned ( ) , range_parameters_tuple)
296
283
}
297
284
298
- #[ pymethod]
299
- fn index ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> PyResult < BigInt > {
300
- if let Ok ( int) = needle. clone ( ) . downcast :: < PyInt > ( ) {
301
- match self . index_of ( int. as_bigint ( ) ) {
302
- Some ( idx) => Ok ( idx) ,
303
- None => Err ( vm. new_value_error ( format ! ( "{int} is not in range" ) ) ) ,
304
- }
305
- } else {
306
- // Fallback to iteration.
307
- Ok ( BigInt :: from_bytes_be (
308
- Sign :: Plus ,
309
- & iter_search (
310
- self . clone ( ) . into_pyobject ( vm) ,
311
- needle,
312
- SearchType :: Index ,
313
- vm,
314
- ) ?
315
- . to_be_bytes ( ) ,
316
- ) )
317
- }
318
- }
319
-
320
- #[ pymethod]
321
- fn count ( & self , item : PyObjectRef , vm : & VirtualMachine ) -> PyResult < usize > {
322
- if let Ok ( int) = item. clone ( ) . downcast :: < PyInt > ( ) {
323
- if self . index_of ( int. as_bigint ( ) ) . is_some ( ) {
324
- Ok ( 1 )
325
- } else {
326
- Ok ( 0 )
327
- }
328
- } else {
329
- // Dealing with classes who might compare equal with ints in their
330
- // __eq__, slow search.
331
- iter_search ( self . clone ( ) . into_pyobject ( vm) , item, SearchType :: Count , vm)
332
- }
333
- }
334
-
335
285
#[ pymethod( magic) ]
336
286
fn getitem ( & self , subscript : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
337
287
match RangeIndex :: try_from_object ( vm, subscript) ? {
@@ -374,6 +324,58 @@ impl PyRange {
374
324
}
375
325
}
376
326
327
+ #[ pyclass]
328
+ impl Py < PyRange > {
329
+ fn contains_inner ( & self , needle : & PyObject , vm : & VirtualMachine ) -> bool {
330
+ // Only accept ints, not subclasses.
331
+ if let Some ( int) = needle. downcast_ref_if_exact :: < PyInt > ( vm) {
332
+ match self . offset ( int. as_bigint ( ) ) {
333
+ Some ( ref offset) => offset. is_multiple_of ( self . step . as_bigint ( ) ) ,
334
+ None => false ,
335
+ }
336
+ } else {
337
+ iter_search ( self . as_object ( ) , needle, SearchType :: Contains , vm) . unwrap_or ( 0 ) != 0
338
+ }
339
+ }
340
+
341
+ #[ pymethod( magic) ]
342
+ fn contains ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> bool {
343
+ self . contains_inner ( & needle, vm)
344
+ }
345
+
346
+ #[ pymethod]
347
+ fn index ( & self , needle : PyObjectRef , vm : & VirtualMachine ) -> PyResult < BigInt > {
348
+ if let Ok ( int) = needle. clone ( ) . downcast :: < PyInt > ( ) {
349
+ match self . index_of ( int. as_bigint ( ) ) {
350
+ Some ( idx) => Ok ( idx) ,
351
+ None => Err ( vm. new_value_error ( format ! ( "{int} is not in range" ) ) ) ,
352
+ }
353
+ } else {
354
+ // Fallback to iteration.
355
+ Ok ( BigInt :: from_bytes_be (
356
+ Sign :: Plus ,
357
+ & iter_search ( self . as_object ( ) , & needle, SearchType :: Index , vm) ?. to_be_bytes ( ) ,
358
+ ) )
359
+ }
360
+ }
361
+
362
+ #[ pymethod]
363
+ fn count ( & self , item : PyObjectRef , vm : & VirtualMachine ) -> PyResult < usize > {
364
+ if let Ok ( int) = item. clone ( ) . downcast :: < PyInt > ( ) {
365
+ let count = if self . index_of ( int. as_bigint ( ) ) . is_some ( ) {
366
+ 1
367
+ } else {
368
+ 0
369
+ } ;
370
+ Ok ( count)
371
+ } else {
372
+ // Dealing with classes who might compare equal with ints in their
373
+ // __eq__, slow search.
374
+ iter_search ( self . as_object ( ) , & item, SearchType :: Count , vm)
375
+ }
376
+ }
377
+ }
378
+
377
379
impl PyRange {
378
380
fn protocol_length ( & self , vm : & VirtualMachine ) -> PyResult < usize > {
379
381
PyInt :: from ( self . len ( ) )
@@ -408,7 +410,7 @@ impl AsSequence for PyRange {
408
410
. ok_or_else( || vm. new_index_error( "index out of range" . to_owned( ) ) )
409
411
} ) ,
410
412
contains : atomic_func ! ( |seq, needle, vm| {
411
- Ok ( PyRange :: sequence_downcast( seq) . contains ( needle. to_owned ( ) , vm) )
413
+ Ok ( PyRange :: sequence_downcast( seq) . contains_inner ( needle, vm) )
412
414
} ) ,
413
415
..PySequenceMethods :: NOT_IMPLEMENTED
414
416
} ) ;
0 commit comments