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