@@ -2402,14 +2402,10 @@ pub trait Step: PartialOrd {
24022402 /// Steps `self` if possible.
24032403 fn step ( & self , by : & Self ) -> Option < Self > ;
24042404
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`.
24062407 ///
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`
24132409 /// without overflow.
24142410 fn steps_between ( start : & Self , end : & Self , by : & Self ) -> Option < usize > ;
24152411}
@@ -2424,9 +2420,16 @@ macro_rules! step_impl_unsigned {
24242420 #[ inline]
24252421 #[ allow( trivial_numeric_casts) ]
24262422 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 {
24282425 // 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+ }
24302433 } else {
24312434 Some ( 0 )
24322435 }
@@ -2444,16 +2447,29 @@ macro_rules! step_impl_signed {
24442447 #[ inline]
24452448 #[ allow( trivial_numeric_casts) ]
24462449 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+ }
24482457 // Note: We assume $t <= isize here
24492458 // Use .wrapping_sub and cast to usize to compute the
24502459 // 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 ;
24552462 } 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)
24572473 }
24582474 }
24592475 }
@@ -2675,6 +2691,16 @@ impl<A: Step + Zero + Clone> Iterator for StepBy<A, ops::Range<A>> {
26752691 None
26762692 }
26772693 }
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+ }
26782704}
26792705
26802706macro_rules! range_exact_iter_impl {
0 commit comments