@@ -2,7 +2,10 @@ use crate::iter::adapters::{
2
2
zip:: try_get_unchecked, TrustedRandomAccess , TrustedRandomAccessNoCoerce ,
3
3
} ;
4
4
use crate :: iter:: { FusedIterator , TrustedLen } ;
5
+ use crate :: mem:: MaybeUninit ;
6
+ use crate :: mem:: SizedTypeProperties ;
5
7
use crate :: ops:: Try ;
8
+ use crate :: { array, ptr} ;
6
9
7
10
/// An iterator that copies the elements of an underlying iterator.
8
11
///
44
47
self . it . next ( ) . copied ( )
45
48
}
46
49
50
+ fn next_chunk < const N : usize > (
51
+ & mut self ,
52
+ ) -> Result < [ Self :: Item ; N ] , array:: IntoIter < Self :: Item , N > >
53
+ where
54
+ Self : Sized ,
55
+ {
56
+ <I as SpecNextChunk < ' _ , N , T > >:: spec_next_chunk ( & mut self . it )
57
+ }
58
+
47
59
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
48
60
self . it . size_hint ( )
49
61
}
@@ -166,3 +178,65 @@ where
166
178
T : Copy ,
167
179
{
168
180
}
181
+
182
+ trait SpecNextChunk < ' a , const N : usize , T : ' a > : Iterator < Item = & ' a T >
183
+ where
184
+ T : Copy ,
185
+ {
186
+ fn spec_next_chunk ( & mut self ) -> Result < [ T ; N ] , array:: IntoIter < T , N > > ;
187
+ }
188
+
189
+ impl < ' a , const N : usize , I , T : ' a > SpecNextChunk < ' a , N , T > for I
190
+ where
191
+ I : Iterator < Item = & ' a T > ,
192
+ T : Copy ,
193
+ {
194
+ default fn spec_next_chunk ( & mut self ) -> Result < [ T ; N ] , array:: IntoIter < T , N > > {
195
+ array:: iter_next_chunk ( & mut self . map ( |e| * e) )
196
+ }
197
+ }
198
+
199
+ impl < ' a , const N : usize , T : ' a > SpecNextChunk < ' a , N , T > for crate :: slice:: Iter < ' a , T >
200
+ where
201
+ T : Copy ,
202
+ {
203
+ fn spec_next_chunk ( & mut self ) -> Result < [ T ; N ] , array:: IntoIter < T , N > > {
204
+ let mut raw_array = MaybeUninit :: uninit_array ( ) ;
205
+
206
+ let len = self . len ( ) ;
207
+
208
+ if T :: IS_ZST {
209
+ if len < N {
210
+ let _ = self . advance_by ( len) ;
211
+ // SAFETY: ZSTs can be conjured ex nihilo; only the amount has to be correct
212
+ return Err ( unsafe { array:: IntoIter :: new_unchecked ( raw_array, 0 ..len) } ) ;
213
+ }
214
+
215
+ let _ = self . advance_by ( N ) ;
216
+ // SAFETY: ditto
217
+ return Ok ( unsafe { MaybeUninit :: array_assume_init ( raw_array) } ) ;
218
+ }
219
+
220
+ if len < N {
221
+ // SAFETY: `len` indicates that this many elements are available and we just checked that
222
+ // it fits into the array.
223
+ unsafe {
224
+ ptr:: copy_nonoverlapping (
225
+ self . as_ref ( ) . as_ptr ( ) ,
226
+ raw_array. as_mut_ptr ( ) as * mut T ,
227
+ len,
228
+ ) ;
229
+ let _ = self . advance_by ( len) ;
230
+ return Err ( array:: IntoIter :: new_unchecked ( raw_array, 0 ..len) ) ;
231
+ }
232
+ }
233
+
234
+ // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize
235
+ // the array.
236
+ unsafe {
237
+ ptr:: copy_nonoverlapping ( self . as_ref ( ) . as_ptr ( ) , raw_array. as_mut_ptr ( ) as * mut T , N ) ;
238
+ let _ = self . advance_by ( N ) ;
239
+ Ok ( MaybeUninit :: array_assume_init ( raw_array) )
240
+ }
241
+ }
242
+ }
0 commit comments