@@ -2402,14 +2402,10 @@ pub trait Step: PartialOrd {
2402
2402
/// Steps `self` if possible.
2403
2403
fn step ( & self , by : & Self ) -> Option < Self > ;
2404
2404
2405
- /// Returns the number of steps between two step objects.
2405
+ /// Returns the number of steps between two step objects. The count is
2406
+ /// inclusive of `start` and exclusive of `end`.
2406
2407
///
2407
- /// `start` should always be less than `end`, so the result should never
2408
- /// be negative.
2409
- ///
2410
- /// `by` must be > 0.
2411
- ///
2412
- /// Returns `None` if it is not possible to calculate steps_between
2408
+ /// Returns `None` if it is not possible to calculate `steps_between`
2413
2409
/// without overflow.
2414
2410
fn steps_between ( start : & Self , end : & Self , by : & Self ) -> Option < usize > ;
2415
2411
}
@@ -2424,9 +2420,16 @@ macro_rules! step_impl_unsigned {
2424
2420
#[ inline]
2425
2421
#[ allow( trivial_numeric_casts) ]
2426
2422
fn steps_between( start: & $t, end: & $t, by: & $t) -> Option <usize > {
2427
- if * start <= * end {
2423
+ if * by == 0 { return None ; }
2424
+ if * start < * end {
2428
2425
// Note: We assume $t <= usize here
2429
- Some ( ( * end - * start) as usize / ( * by as usize ) )
2426
+ let diff = ( * end - * start) as usize ;
2427
+ let by = * by as usize ;
2428
+ if diff % by > 0 {
2429
+ Some ( diff / by + 1 )
2430
+ } else {
2431
+ Some ( diff / by)
2432
+ }
2430
2433
} else {
2431
2434
Some ( 0 )
2432
2435
}
@@ -2444,16 +2447,29 @@ macro_rules! step_impl_signed {
2444
2447
#[ inline]
2445
2448
#[ allow( trivial_numeric_casts) ]
2446
2449
fn steps_between( start: & $t, end: & $t, by: & $t) -> Option <usize > {
2447
- if * start <= * end {
2450
+ if * by == 0 { return None ; }
2451
+ let mut diff: usize ;
2452
+ let mut by_u: usize ;
2453
+ if * by > 0 {
2454
+ if * start >= * end {
2455
+ return Some ( 0 ) ;
2456
+ }
2448
2457
// Note: We assume $t <= isize here
2449
2458
// Use .wrapping_sub and cast to usize to compute the
2450
2459
// 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
- )
2460
+ diff = ( * end as isize ) . wrapping_sub( * start as isize ) as usize ;
2461
+ by_u = * by as usize ;
2455
2462
} else {
2456
- Some ( 0 )
2463
+ if * start <= * end {
2464
+ return Some ( 0 ) ;
2465
+ }
2466
+ diff = ( * start as isize ) . wrapping_sub( * end as isize ) as usize ;
2467
+ by_u = ( * by as isize ) . wrapping_mul( -1 ) as usize ;
2468
+ }
2469
+ if diff % by_u > 0 {
2470
+ Some ( diff / by_u + 1 )
2471
+ } else {
2472
+ Some ( diff / by_u)
2457
2473
}
2458
2474
}
2459
2475
}
@@ -2675,6 +2691,16 @@ impl<A: Step + Zero + Clone> Iterator for StepBy<A, ops::Range<A>> {
2675
2691
None
2676
2692
}
2677
2693
}
2694
+
2695
+ #[ inline]
2696
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
2697
+ match Step :: steps_between ( & self . range . start ,
2698
+ & self . range . end ,
2699
+ & self . step_by ) {
2700
+ Some ( hint) => ( hint, Some ( hint) ) ,
2701
+ None => ( 0 , None )
2702
+ }
2703
+ }
2678
2704
}
2679
2705
2680
2706
macro_rules! range_exact_iter_impl {
0 commit comments