@@ -2407,12 +2407,14 @@ pub trait Step: PartialOrd {
2407
2407
/// `start` should always be less than `end`, so the result should never
2408
2408
/// be negative.
2409
2409
///
2410
+ /// `by` must be > 0.
2411
+ ///
2410
2412
/// Returns `None` if it is not possible to calculate steps_between
2411
2413
/// without overflow.
2412
2414
fn steps_between ( start : & Self , end : & Self , by : & Self ) -> Option < usize > ;
2413
2415
}
2414
2416
2415
- macro_rules! step_impl {
2417
+ macro_rules! step_impl_unsigned {
2416
2418
( $( $t: ty) * ) => ( $(
2417
2419
impl Step for $t {
2418
2420
#[ inline]
@@ -2423,7 +2425,33 @@ macro_rules! step_impl {
2423
2425
#[ allow( trivial_numeric_casts) ]
2424
2426
fn steps_between( start: & $t, end: & $t, by: & $t) -> Option <usize > {
2425
2427
if * start <= * end {
2426
- Some ( ( ( * end - * start) / * by) as usize )
2428
+ // Note: We assume $t <= usize here
2429
+ Some ( ( * end - * start) as usize / ( * by as usize ) )
2430
+ } else {
2431
+ Some ( 0 )
2432
+ }
2433
+ }
2434
+ }
2435
+ ) * )
2436
+ }
2437
+ macro_rules! step_impl_signed {
2438
+ ( $( $t: ty) * ) => ( $(
2439
+ impl Step for $t {
2440
+ #[ inline]
2441
+ fn step( & self , by: & $t) -> Option <$t> {
2442
+ ( * self ) . checked_add( * by)
2443
+ }
2444
+ #[ inline]
2445
+ #[ allow( trivial_numeric_casts) ]
2446
+ fn steps_between( start: & $t, end: & $t, by: & $t) -> Option <usize > {
2447
+ if * start <= * end {
2448
+ // Note: We assume $t <= isize here
2449
+ // Use .wrapping_sub and cast to usize to compute the
2450
+ // difference that may not fit inside the range of isize.
2451
+ Some (
2452
+ ( ( * end as isize ) . wrapping_sub( * start as isize ) as usize
2453
+ / ( * by as usize ) )
2454
+ )
2427
2455
} else {
2428
2456
Some ( 0 )
2429
2457
}
@@ -2447,9 +2475,12 @@ macro_rules! step_impl_no_between {
2447
2475
) * )
2448
2476
}
2449
2477
2450
- step_impl ! ( usize u8 u16 u32 isize i8 i16 i32 ) ;
2478
+ step_impl_unsigned ! ( usize u8 u16 u32 ) ;
2479
+ step_impl_signed ! ( isize i8 i16 i32 ) ;
2480
+ #[ cfg( target_pointer_width = "64" ) ]
2481
+ step_impl_unsigned ! ( u64 ) ;
2451
2482
#[ cfg( target_pointer_width = "64" ) ]
2452
- step_impl ! ( u64 i64 ) ;
2483
+ step_impl_signed ! ( i64 ) ;
2453
2484
#[ cfg( target_pointer_width = "32" ) ]
2454
2485
step_impl_no_between ! ( u64 i64 ) ;
2455
2486
0 commit comments