@@ -780,24 +780,27 @@ where
780780}
781781
782782/// Pulls `N` items from `iter` and returns them as an array. If the iterator
783- /// yields fewer than `N` items, `None ` is returned and all already yielded
784- /// items are dropped .
783+ /// yields fewer than `N` items, `Err ` is returned containing an iterator over
784+ /// the already yielded items .
785785///
786786/// Since the iterator is passed as a mutable reference and this function calls
787787/// `next` at most `N` times, the iterator can still be used afterwards to
788788/// retrieve the remaining items.
789789///
790790/// If `iter.next()` panicks, all items already yielded by the iterator are
791791/// dropped.
792- fn try_collect_into_array < I , T , R , const N : usize > ( iter : & mut I ) -> Option < R :: TryType >
792+ #[ inline]
793+ fn try_collect_into_array < I , T , R , const N : usize > (
794+ iter : & mut I ,
795+ ) -> Result < R :: TryType , IntoIter < T , N > >
793796where
794797 I : Iterator ,
795798 I :: Item : Try < Output = T , Residual = R > ,
796799 R : Residual < [ T ; N ] > ,
797800{
798801 if N == 0 {
799802 // SAFETY: An empty array is always inhabited and has no validity invariants.
800- return unsafe { Some ( Try :: from_output ( mem:: zeroed ( ) ) ) } ;
803+ return Ok ( Try :: from_output ( unsafe { mem:: zeroed ( ) } ) ) ;
801804 }
802805
803806 struct Guard < ' a , T , const N : usize > {
@@ -821,35 +824,49 @@ where
821824 let mut array = MaybeUninit :: uninit_array :: < N > ( ) ;
822825 let mut guard = Guard { array_mut : & mut array, initialized : 0 } ;
823826
824- while let Some ( item_rslt) = iter. next ( ) {
825- let item = match item_rslt. branch ( ) {
826- ControlFlow :: Break ( r) => {
827- return Some ( FromResidual :: from_residual ( r) ) ;
827+ for _ in 0 ..N {
828+ match iter. next ( ) {
829+ Some ( item_rslt) => {
830+ let item = match item_rslt. branch ( ) {
831+ ControlFlow :: Break ( r) => {
832+ return Ok ( FromResidual :: from_residual ( r) ) ;
833+ }
834+ ControlFlow :: Continue ( elem) => elem,
835+ } ;
836+
837+ // SAFETY: `guard.initialized` starts at 0, is increased by one in the
838+ // loop and the loop is aborted once it reaches N (which is
839+ // `array.len()`).
840+ unsafe {
841+ guard. array_mut . get_unchecked_mut ( guard. initialized ) . write ( item) ;
842+ }
843+ guard. initialized += 1 ;
844+ }
845+ None => {
846+ let alive = 0 ..guard. initialized ;
847+ mem:: forget ( guard) ;
848+ // SAFETY: `array` was initialized with exactly `initialized`
849+ // number of elements.
850+ return Err ( unsafe { IntoIter :: new_unchecked ( array, alive) } ) ;
828851 }
829- ControlFlow :: Continue ( elem) => elem,
830- } ;
831-
832- // SAFETY: `guard.initialized` starts at 0, is increased by one in the
833- // loop and the loop is aborted once it reaches N (which is
834- // `array.len()`).
835- unsafe {
836- guard. array_mut . get_unchecked_mut ( guard. initialized ) . write ( item) ;
837- }
838- guard. initialized += 1 ;
839-
840- // Check if the whole array was initialized.
841- if guard. initialized == N {
842- mem:: forget ( guard) ;
843-
844- // SAFETY: the condition above asserts that all elements are
845- // initialized.
846- let out = unsafe { MaybeUninit :: array_assume_init ( array) } ;
847- return Some ( Try :: from_output ( out) ) ;
848852 }
849853 }
850854
851- // This is only reached if the iterator is exhausted before
852- // `guard.initialized` reaches `N`. Also note that `guard` is dropped here,
853- // dropping all already initialized elements.
854- None
855+ mem:: forget ( guard) ;
856+ // SAFETY: All elements of the array were populated in the loop above.
857+ let output = unsafe { MaybeUninit :: array_assume_init ( array) } ;
858+ Ok ( Try :: from_output ( output) )
859+ }
860+
861+ /// Returns the next chunk of `N` items from the iterator or errors with an
862+ /// iterator over the remainder. Used for `Iterator::next_chunk`.
863+ #[ inline]
864+ pub ( crate ) fn iter_next_chunk < I , const N : usize > (
865+ iter : & mut I ,
866+ ) -> Result < [ I :: Item ; N ] , IntoIter < I :: Item , N > >
867+ where
868+ I : Iterator ,
869+ {
870+ let mut map = iter. map ( NeverShortCircuit ) ;
871+ try_collect_into_array ( & mut map) . map ( |NeverShortCircuit ( arr) | arr)
855872}
0 commit comments