@@ -285,7 +285,6 @@ impl<'py, T: Element, I: IterMode> NpySingleIterBuilder<'py, T, I> {
285
285
pub struct NpySingleIter < ' py , T , I > {
286
286
iterator : ptr:: NonNull < NpyIter > ,
287
287
iternext : unsafe extern "C" fn ( * mut NpyIter ) -> c_int ,
288
- empty : bool ,
289
288
iter_size : npy_intp ,
290
289
dataptr : * mut * mut c_char ,
291
290
return_type : PhantomData < T > ,
@@ -324,7 +323,6 @@ impl<'py, T, I> NpySingleIter<'py, T, I> {
324
323
iterator,
325
324
iternext,
326
325
iter_size,
327
- empty : iter_size == 0 ,
328
326
dataptr,
329
327
return_type : PhantomData ,
330
328
mode : PhantomData ,
@@ -334,15 +332,18 @@ impl<'py, T, I> NpySingleIter<'py, T, I> {
334
332
}
335
333
336
334
fn iternext ( & mut self ) -> Option < * mut T > {
337
- if self . empty {
335
+ if self . iter_size == 0 {
338
336
None
339
337
} else {
340
338
// Note: This pointer is correct and doesn't need to be updated,
341
339
// note that we're derefencing a **char into a *char casting to a *T
342
340
// and then transforming that into a reference, the value that dataptr
343
341
// points to is being updated by iternext to point to the next value.
344
342
let ret = unsafe { * self . dataptr as * mut T } ;
345
- self . empty = unsafe { ( self . iternext ) ( self . iterator . as_mut ( ) ) } == 0 ;
343
+ let empty = unsafe { ( self . iternext ) ( self . iterator . as_mut ( ) ) } == 0 ;
344
+ debug_assert_ne ! ( self . iter_size, 0 ) ;
345
+ self . iter_size -= 1 ;
346
+ debug_assert ! ( self . iter_size > 0 || empty) ;
346
347
Some ( ret)
347
348
}
348
349
}
@@ -368,7 +369,13 @@ impl<'py, T: 'py> Iterator for NpySingleIter<'py, T, Readonly> {
368
369
}
369
370
370
371
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
371
- ( self . iter_size as usize , Some ( self . iter_size as usize ) )
372
+ ( self . len ( ) , Some ( self . len ( ) ) )
373
+ }
374
+ }
375
+
376
+ impl < ' py , T : ' py > ExactSizeIterator for NpySingleIter < ' py , T , Readonly > {
377
+ fn len ( & self ) -> usize {
378
+ self . iter_size as usize
372
379
}
373
380
}
374
381
@@ -380,7 +387,13 @@ impl<'py, T: 'py> Iterator for NpySingleIter<'py, T, ReadWrite> {
380
387
}
381
388
382
389
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
383
- ( self . iter_size as usize , Some ( self . iter_size as usize ) )
390
+ ( self . len ( ) , Some ( self . len ( ) ) )
391
+ }
392
+ }
393
+
394
+ impl < ' py , T : ' py > ExactSizeIterator for NpySingleIter < ' py , T , ReadWrite > {
395
+ fn len ( & self ) -> usize {
396
+ self . iter_size as usize
384
397
}
385
398
}
386
399
@@ -528,7 +541,6 @@ impl<'py, T: Element, S: MultiIterModeWithManyArrays> NpyMultiIterBuilder<'py, T
528
541
pub struct NpyMultiIter < ' py , T , S : MultiIterModeWithManyArrays > {
529
542
iterator : ptr:: NonNull < NpyIter > ,
530
543
iternext : unsafe extern "C" fn ( * mut NpyIter ) -> c_int ,
531
- empty : bool ,
532
544
iter_size : npy_intp ,
533
545
dataptr : * mut * mut c_char ,
534
546
marker : PhantomData < ( T , S ) > ,
@@ -568,7 +580,6 @@ impl<'py, T, S: MultiIterModeWithManyArrays> NpyMultiIter<'py, T, S> {
568
580
iterator,
569
581
iternext,
570
582
iter_size,
571
- empty : iter_size == 0 ,
572
583
dataptr,
573
584
marker : PhantomData ,
574
585
arrays,
@@ -596,7 +607,7 @@ macro_rules! impl_multi_iter {
596
607
type Item = ( $( $ty, ) +) ;
597
608
598
609
fn next( & mut self ) -> Option <Self :: Item > {
599
- if self . empty {
610
+ if self . iter_size == 0 {
600
611
None
601
612
} else {
602
613
// Note: This pointer is correct and doesn't need to be updated,
@@ -605,13 +616,22 @@ macro_rules! impl_multi_iter {
605
616
// points to is being updated by iternext to point to the next value.
606
617
let ( $( $ptr, ) +) = unsafe { $expand:: <T >( self . dataptr) } ;
607
618
let retval = Some ( unsafe { $deref } ) ;
608
- self . empty = unsafe { ( self . iternext) ( self . iterator. as_mut( ) ) } == 0 ;
619
+ let empty = unsafe { ( self . iternext) ( self . iterator. as_mut( ) ) } == 0 ;
620
+ debug_assert_ne!( self . iter_size, 0 ) ;
621
+ self . iter_size -= 1 ;
622
+ debug_assert!( self . iter_size > 0 || empty) ;
609
623
retval
610
624
}
611
625
}
612
626
613
627
fn size_hint( & self ) -> ( usize , Option <usize >) {
614
- ( self . iter_size as usize , Some ( self . iter_size as usize ) )
628
+ ( self . len( ) , Some ( self . len( ) ) )
629
+ }
630
+ }
631
+
632
+ impl <' py, T : ' py> ExactSizeIterator for NpyMultiIter <' py, T , $structure> {
633
+ fn len( & self ) -> usize {
634
+ self . iter_size as usize
615
635
}
616
636
}
617
637
} ;
0 commit comments