1
1
use crate :: {
2
2
intrinsics,
3
3
iter:: { from_fn, TrustedLen , TrustedRandomAccess } ,
4
+ num:: NonZeroUsize ,
4
5
ops:: { Range , Try } ,
5
6
} ;
6
7
@@ -22,7 +23,11 @@ pub struct StepBy<I> {
22
23
/// Additionally this type-dependent preprocessing means specialized implementations
23
24
/// cannot be used interchangeably.
24
25
iter : I ,
25
- step : usize ,
26
+ /// This field is `step - 1`, aka the correct amount to pass to `nth` when iterating.
27
+ /// It MUST NOT be `usize::MAX`, as `unsafe` code depends on being able to add one
28
+ /// without the risk of overflow. (This is important so that length calculations
29
+ /// don't need to check for division-by-zero, for example.)
30
+ step_minus_one : usize ,
26
31
first_take : bool ,
27
32
}
28
33
@@ -31,7 +36,16 @@ impl<I> StepBy<I> {
31
36
pub ( in crate :: iter) fn new ( iter : I , step : usize ) -> StepBy < I > {
32
37
assert ! ( step != 0 ) ;
33
38
let iter = <I as SpecRangeSetup < I > >:: setup ( iter, step) ;
34
- StepBy { iter, step : step - 1 , first_take : true }
39
+ StepBy { iter, step_minus_one : step - 1 , first_take : true }
40
+ }
41
+
42
+ /// The `step` that was originally passed to `Iterator::step_by(step)`,
43
+ /// aka `self.step_minus_one + 1`.
44
+ #[ inline]
45
+ fn original_step ( & self ) -> NonZeroUsize {
46
+ // SAFETY: By type invariant, `step_minus_one` cannot be `MAX`, which
47
+ // means the addition cannot overflow and the result cannot be zero.
48
+ unsafe { NonZeroUsize :: new_unchecked ( intrinsics:: unchecked_add ( self . step_minus_one , 1 ) ) }
35
49
}
36
50
}
37
51
81
95
// The zero-based index starting from the end of the iterator of the
82
96
// last element. Used in the `DoubleEndedIterator` implementation.
83
97
fn next_back_index ( & self ) -> usize {
84
- let rem = self . iter . len ( ) % ( self . step + 1 ) ;
85
- if self . first_take { if rem == 0 { self . step } else { rem - 1 } } else { rem }
98
+ let rem = self . iter . len ( ) % self . original_step ( ) ;
99
+ if self . first_take { if rem == 0 { self . step_minus_one } else { rem - 1 } } else { rem }
86
100
}
87
101
}
88
102
@@ -209,30 +223,30 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
209
223
210
224
#[ inline]
211
225
default fn spec_next ( & mut self ) -> Option < I :: Item > {
212
- let step_size = if self . first_take { 0 } else { self . step } ;
226
+ let step_size = if self . first_take { 0 } else { self . step_minus_one } ;
213
227
self . first_take = false ;
214
228
self . iter . nth ( step_size)
215
229
}
216
230
217
231
#[ inline]
218
232
default fn spec_size_hint ( & self ) -> ( usize , Option < usize > ) {
219
233
#[ inline]
220
- fn first_size ( step : usize ) -> impl Fn ( usize ) -> usize {
221
- move |n| if n == 0 { 0 } else { 1 + ( n - 1 ) / ( step + 1 ) }
234
+ fn first_size ( step : NonZeroUsize ) -> impl Fn ( usize ) -> usize {
235
+ move |n| if n == 0 { 0 } else { 1 + ( n - 1 ) / step }
222
236
}
223
237
224
238
#[ inline]
225
- fn other_size ( step : usize ) -> impl Fn ( usize ) -> usize {
226
- move |n| n / ( step + 1 )
239
+ fn other_size ( step : NonZeroUsize ) -> impl Fn ( usize ) -> usize {
240
+ move |n| n / step
227
241
}
228
242
229
243
let ( low, high) = self . iter . size_hint ( ) ;
230
244
231
245
if self . first_take {
232
- let f = first_size ( self . step ) ;
246
+ let f = first_size ( self . original_step ( ) ) ;
233
247
( f ( low) , high. map ( f) )
234
248
} else {
235
- let f = other_size ( self . step ) ;
249
+ let f = other_size ( self . original_step ( ) ) ;
236
250
( f ( low) , high. map ( f) )
237
251
}
238
252
}
@@ -247,10 +261,9 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
247
261
}
248
262
n -= 1 ;
249
263
}
250
- // n and self.step are indices, we need to add 1 to get the amount of elements
264
+ // n and self.step_minus_one are indices, we need to add 1 to get the amount of elements
251
265
// When calling `.nth`, we need to subtract 1 again to convert back to an index
252
- // step + 1 can't overflow because `.step_by` sets `self.step` to `step - 1`
253
- let mut step = self . step + 1 ;
266
+ let mut step = self . original_step ( ) . get ( ) ;
254
267
// n + 1 could overflow
255
268
// thus, if n is usize::MAX, instead of adding one, we call .nth(step)
256
269
if n == usize:: MAX {
@@ -288,8 +301,11 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
288
301
R : Try < Output = Acc > ,
289
302
{
290
303
#[ inline]
291
- fn nth < I : Iterator > ( iter : & mut I , step : usize ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
292
- move || iter. nth ( step)
304
+ fn nth < I : Iterator > (
305
+ iter : & mut I ,
306
+ step_minus_one : usize ,
307
+ ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
308
+ move || iter. nth ( step_minus_one)
293
309
}
294
310
295
311
if self . first_take {
@@ -299,16 +315,19 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
299
315
Some ( x) => acc = f ( acc, x) ?,
300
316
}
301
317
}
302
- from_fn ( nth ( & mut self . iter , self . step ) ) . try_fold ( acc, f)
318
+ from_fn ( nth ( & mut self . iter , self . step_minus_one ) ) . try_fold ( acc, f)
303
319
}
304
320
305
321
default fn spec_fold < Acc , F > ( mut self , mut acc : Acc , mut f : F ) -> Acc
306
322
where
307
323
F : FnMut ( Acc , Self :: Item ) -> Acc ,
308
324
{
309
325
#[ inline]
310
- fn nth < I : Iterator > ( iter : & mut I , step : usize ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
311
- move || iter. nth ( step)
326
+ fn nth < I : Iterator > (
327
+ iter : & mut I ,
328
+ step_minus_one : usize ,
329
+ ) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
330
+ move || iter. nth ( step_minus_one)
312
331
}
313
332
314
333
if self . first_take {
@@ -318,7 +337,7 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
318
337
Some ( x) => acc = f ( acc, x) ,
319
338
}
320
339
}
321
- from_fn ( nth ( & mut self . iter , self . step ) ) . fold ( acc, f)
340
+ from_fn ( nth ( & mut self . iter , self . step_minus_one ) ) . fold ( acc, f)
322
341
}
323
342
}
324
343
@@ -336,7 +355,7 @@ unsafe impl<I: DoubleEndedIterator + ExactSizeIterator> StepByBackImpl<I> for St
336
355
// is out of bounds because the length of `self.iter` does not exceed
337
356
// `usize::MAX` (because `I: ExactSizeIterator`) and `nth_back` is
338
357
// zero-indexed
339
- let n = n. saturating_mul ( self . step + 1 ) . saturating_add ( self . next_back_index ( ) ) ;
358
+ let n = n. saturating_mul ( self . original_step ( ) . get ( ) ) . saturating_add ( self . next_back_index ( ) ) ;
340
359
self . iter . nth_back ( n)
341
360
}
342
361
@@ -348,16 +367,16 @@ unsafe impl<I: DoubleEndedIterator + ExactSizeIterator> StepByBackImpl<I> for St
348
367
#[ inline]
349
368
fn nth_back < I : DoubleEndedIterator > (
350
369
iter : & mut I ,
351
- step : usize ,
370
+ step_minus_one : usize ,
352
371
) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
353
- move || iter. nth_back ( step )
372
+ move || iter. nth_back ( step_minus_one )
354
373
}
355
374
356
375
match self . next_back ( ) {
357
376
None => try { init } ,
358
377
Some ( x) => {
359
378
let acc = f ( init, x) ?;
360
- from_fn ( nth_back ( & mut self . iter , self . step ) ) . try_fold ( acc, f)
379
+ from_fn ( nth_back ( & mut self . iter , self . step_minus_one ) ) . try_fold ( acc, f)
361
380
}
362
381
}
363
382
}
@@ -371,16 +390,16 @@ unsafe impl<I: DoubleEndedIterator + ExactSizeIterator> StepByBackImpl<I> for St
371
390
#[ inline]
372
391
fn nth_back < I : DoubleEndedIterator > (
373
392
iter : & mut I ,
374
- step : usize ,
393
+ step_minus_one : usize ,
375
394
) -> impl FnMut ( ) -> Option < I :: Item > + ' _ {
376
- move || iter. nth_back ( step )
395
+ move || iter. nth_back ( step_minus_one )
377
396
}
378
397
379
398
match self . next_back ( ) {
380
399
None => init,
381
400
Some ( x) => {
382
401
let acc = f ( init, x) ;
383
- from_fn ( nth_back ( & mut self . iter , self . step ) ) . fold ( acc, f)
402
+ from_fn ( nth_back ( & mut self . iter , self . step_minus_one ) ) . fold ( acc, f)
384
403
}
385
404
}
386
405
}
@@ -424,8 +443,7 @@ macro_rules! spec_int_ranges {
424
443
fn spec_next( & mut self ) -> Option <$t> {
425
444
// if a step size larger than the type has been specified fall back to
426
445
// t::MAX, in which case remaining will be at most 1.
427
- // The `+ 1` can't overflow since the constructor substracted 1 from the original value.
428
- let step = <$t>:: try_from( self . step + 1 ) . unwrap_or( <$t>:: MAX ) ;
446
+ let step = <$t>:: try_from( self . original_step( ) . get( ) ) . unwrap_or( <$t>:: MAX ) ;
429
447
let remaining = self . iter. end;
430
448
if remaining > 0 {
431
449
let val = self . iter. start;
@@ -474,7 +492,7 @@ macro_rules! spec_int_ranges {
474
492
{
475
493
// if a step size larger than the type has been specified fall back to
476
494
// t::MAX, in which case remaining will be at most 1.
477
- let step = <$t>:: try_from( self . step + 1 ) . unwrap_or( <$t>:: MAX ) ;
495
+ let step = <$t>:: try_from( self . original_step ( ) . get ( ) ) . unwrap_or( <$t>:: MAX ) ;
478
496
let remaining = self . iter. end;
479
497
let mut acc = init;
480
498
let mut val = self . iter. start;
@@ -500,7 +518,7 @@ macro_rules! spec_int_ranges_r {
500
518
fn spec_next_back( & mut self ) -> Option <Self :: Item >
501
519
where Range <$t>: DoubleEndedIterator + ExactSizeIterator ,
502
520
{
503
- let step = ( self . step + 1 ) as $t;
521
+ let step = self . original_step ( ) . get ( ) as $t;
504
522
let remaining = self . iter. end;
505
523
if remaining > 0 {
506
524
let start = self . iter. start;
0 commit comments