1
- use num_bigint:: BigInt ;
2
- use num_traits:: { One , Signed , ToPrimitive , Zero } ;
1
+ use num_traits:: ToPrimitive ;
3
2
use std:: ops:: Range ;
4
3
5
4
use crate :: builtins:: int:: PyInt ;
6
- use crate :: builtins:: slice:: { PySlice , PySliceRef } ;
5
+ use crate :: builtins:: slice:: { saturate_index , PySlice , PySliceRef , SaturatedIndices } ;
7
6
use crate :: utils:: Either ;
8
7
use crate :: VirtualMachine ;
9
8
use crate :: { PyObjectRef , PyResult , TypeProtocol } ;
@@ -27,7 +26,8 @@ pub trait PySliceableSequenceMut {
27
26
slice : & PySlice ,
28
27
items : & [ Self :: Item ] ,
29
28
) -> PyResult < ( ) > {
30
- let ( range, step, is_negative_step) = convert_slice ( slice, self . as_slice ( ) . len ( ) , vm) ?;
29
+ let ( range, step, is_negative_step) =
30
+ SaturatedIndices :: new ( slice, vm) ?. adjust_indices ( self . as_slice ( ) . len ( ) ) ;
31
31
if !is_negative_step && step == Some ( 1 ) {
32
32
return if range. end - range. start == items. len ( ) {
33
33
self . do_set_range ( range, items) ;
@@ -85,7 +85,8 @@ pub trait PySliceableSequenceMut {
85
85
slice : & PySlice ,
86
86
items : & [ Self :: Item ] ,
87
87
) -> PyResult < ( ) > {
88
- let ( range, step, is_negative_step) = convert_slice ( slice, self . as_slice ( ) . len ( ) , vm) ?;
88
+ let ( range, step, is_negative_step) =
89
+ SaturatedIndices :: new ( slice, vm) ?. adjust_indices ( self . as_slice ( ) . len ( ) ) ;
89
90
if !is_negative_step && step == Some ( 1 ) {
90
91
self . do_set_range ( range, items) ;
91
92
return Ok ( ( ) ) ;
@@ -136,7 +137,8 @@ pub trait PySliceableSequenceMut {
136
137
}
137
138
138
139
fn delete_slice ( & mut self , vm : & VirtualMachine , slice : & PySlice ) -> PyResult < ( ) > {
139
- let ( range, step, is_negative_step) = convert_slice ( slice, self . as_slice ( ) . len ( ) , vm) ?;
140
+ let ( range, step, is_negative_step) =
141
+ SaturatedIndices :: new ( slice, vm) ?. adjust_indices ( self . as_slice ( ) . len ( ) ) ;
140
142
if range. start >= range. end {
141
143
return Ok ( ( ) ) ;
142
144
}
@@ -228,19 +230,12 @@ pub trait PySliceableSequence {
228
230
}
229
231
230
232
fn saturate_index ( & self , p : isize ) -> usize {
231
- saturate_index ( p, self . len ( ) )
232
- }
233
-
234
- fn saturate_big_index ( & self , slice_pos : & BigInt ) -> usize {
235
- saturate_big_index ( slice_pos, self . len ( ) )
236
- }
237
-
238
- fn saturate_range ( & self , start : & Option < BigInt > , stop : & Option < BigInt > ) -> Range < usize > {
239
- saturate_range ( start, stop, self . len ( ) )
233
+ saturate_index ( p, self . len ( ) as isize )
240
234
}
241
235
242
236
fn get_slice_items ( & self , vm : & VirtualMachine , slice : & PySlice ) -> PyResult < Self :: Sliced > {
243
- let ( range, step, is_negative_step) = convert_slice ( slice, self . len ( ) , vm) ?;
237
+ let ( range, step, is_negative_step) =
238
+ SaturatedIndices :: new ( slice, vm) ?. adjust_indices ( self . len ( ) ) ;
244
239
if range. start >= range. end {
245
240
return Ok ( Self :: empty ( ) ) ;
246
241
}
@@ -395,100 +390,4 @@ pub(crate) fn wrap_index(p: isize, len: usize) -> Option<usize> {
395
390
} else {
396
391
Some ( p)
397
392
}
398
- }
399
-
400
- // return pos is in range [0, len] inclusive
401
- pub fn saturate_index ( p : isize , len : usize ) -> usize {
402
- let mut p = p;
403
- let len = len. to_isize ( ) . unwrap ( ) ;
404
- if p < 0 {
405
- p += len;
406
- if p < 0 {
407
- p = 0 ;
408
- }
409
- }
410
- if p > len {
411
- p = len;
412
- }
413
- p as usize
414
- }
415
-
416
- fn saturate_big_index ( slice_pos : & BigInt , len : usize ) -> usize {
417
- if let Some ( pos) = slice_pos. to_isize ( ) {
418
- saturate_index ( pos, len)
419
- } else if slice_pos. is_negative ( ) {
420
- // slice past start bound, round to start
421
- 0
422
- } else {
423
- // slice past end bound, round to end
424
- len
425
- }
426
- }
427
-
428
- pub ( crate ) fn saturate_range (
429
- start : & Option < BigInt > ,
430
- stop : & Option < BigInt > ,
431
- len : usize ,
432
- ) -> Range < usize > {
433
- let start = start. as_ref ( ) . map_or ( 0 , |x| saturate_big_index ( x, len) ) ;
434
- let stop = stop. as_ref ( ) . map_or ( len, |x| saturate_big_index ( x, len) ) ;
435
-
436
- start..stop
437
- }
438
-
439
- pub ( crate ) fn convert_slice (
440
- slice : & PySlice ,
441
- len : usize ,
442
- vm : & VirtualMachine ,
443
- ) -> PyResult < ( Range < usize > , Option < usize > , bool ) > {
444
- let start = slice. start_index ( vm) ?;
445
- let stop = slice. stop_index ( vm) ?;
446
- let step = slice. step_index ( vm) ?. unwrap_or_else ( BigInt :: one) ;
447
-
448
- if step. is_zero ( ) {
449
- return Err ( vm. new_value_error ( "slice step cannot be zero" . to_owned ( ) ) ) ;
450
- }
451
-
452
- let ( start, stop, step, is_negative_step) = if step. is_negative ( ) {
453
- (
454
- stop. map ( |x| {
455
- if x == -BigInt :: one ( ) {
456
- len + BigInt :: one ( )
457
- } else {
458
- x + 1
459
- }
460
- } ) ,
461
- start. map ( |x| {
462
- if x == -BigInt :: one ( ) {
463
- BigInt :: from ( len)
464
- } else {
465
- x + 1
466
- }
467
- } ) ,
468
- -step,
469
- true ,
470
- )
471
- } else {
472
- ( start, stop, step, false )
473
- } ;
474
-
475
- let step = step. to_usize ( ) ;
476
-
477
- let range = saturate_range ( & start, & stop, len) ;
478
- let range = if range. start >= range. end {
479
- range. start ..range. start
480
- } else {
481
- // step overflow
482
- if step. is_none ( ) {
483
- if is_negative_step {
484
- ( range. end - 1 ) ..range. end
485
- } else {
486
- range. start ..( range. start + 1 )
487
- }
488
- } else {
489
- range
490
- }
491
- } ;
492
-
493
- Ok ( ( range, step, is_negative_step) )
494
- }
393
+ }
0 commit comments