@@ -161,21 +161,43 @@ where
161161 }
162162}
163163
164- struct ArrayBuilder < T , N : ArrayLength < T > > {
164+ /// Creates an array one element at a time using a mutable iterator
165+ /// you can write to with `ptr::write`.
166+ ///
167+ /// Incremenent the position while iterating to mark off created elements,
168+ /// which will be dropped if `into_inner` is not called.
169+ #[ doc( hidden) ]
170+ pub struct ArrayBuilder < T , N : ArrayLength < T > > {
165171 array : ManuallyDrop < GenericArray < T , N > > ,
166172 position : usize ,
167173}
168174
169175impl < T , N : ArrayLength < T > > ArrayBuilder < T , N > {
170- fn new ( ) -> ArrayBuilder < T , N > {
176+ #[ doc( hidden) ]
177+ #[ inline]
178+ pub unsafe fn new ( ) -> ArrayBuilder < T , N > {
171179 ArrayBuilder {
172- array : ManuallyDrop :: new ( unsafe { mem:: uninitialized ( ) } ) ,
180+ array : ManuallyDrop :: new ( mem:: uninitialized ( ) ) ,
173181 position : 0 ,
174182 }
175183 }
176184
177- fn into_inner ( self ) -> GenericArray < T , N > {
178- let array = unsafe { ptr:: read ( & self . array ) } ;
185+ /// Creates a mutable iterator for writing to the array using `ptr::write`.
186+ ///
187+ /// Increment the position value given as a mutable reference as you iterate
188+ /// to mark how many elements have been created.
189+ #[ doc( hidden) ]
190+ #[ inline]
191+ pub unsafe fn iter_position ( & mut self ) -> ( slice:: IterMut < T > , & mut usize ) {
192+ ( self . array . iter_mut ( ) , & mut self . position )
193+ }
194+
195+ /// When done writing (assuming all elements have been written to),
196+ /// get the inner array.
197+ #[ doc( hidden) ]
198+ #[ inline]
199+ pub unsafe fn into_inner ( self ) -> GenericArray < T , N > {
200+ let array = ptr:: read ( & self . array ) ;
179201
180202 mem:: forget ( self ) ;
181203
@@ -185,33 +207,50 @@ impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {
185207
186208impl < T , N : ArrayLength < T > > Drop for ArrayBuilder < T , N > {
187209 fn drop ( & mut self ) {
188- for value in self . array . iter_mut ( ) . take ( self . position ) {
210+ for value in & mut self . array [ .. self . position ] {
189211 unsafe {
190212 ptr:: drop_in_place ( value) ;
191213 }
192214 }
193215 }
194216}
195217
196- struct ArrayConsumer < T , N : ArrayLength < T > > {
218+ /// Consumes an array.
219+ ///
220+ /// Increment the position while iterating and any leftover elements
221+ /// will be dropped if position does not go to N
222+ #[ doc( hidden) ]
223+ pub struct ArrayConsumer < T , N : ArrayLength < T > > {
197224 array : ManuallyDrop < GenericArray < T , N > > ,
198225 position : usize ,
199226}
200227
201228impl < T , N : ArrayLength < T > > ArrayConsumer < T , N > {
202- fn new ( array : GenericArray < T , N > ) -> ArrayConsumer < T , N > {
229+ #[ doc( hidden) ]
230+ #[ inline]
231+ pub unsafe fn new ( array : GenericArray < T , N > ) -> ArrayConsumer < T , N > {
203232 ArrayConsumer {
204233 array : ManuallyDrop :: new ( array) ,
205234 position : 0 ,
206235 }
207236 }
237+
238+ /// Creates an iterator and mutable reference to the internal position
239+ /// to keep track of consumed elements.
240+ ///
241+ /// Increment the position as you iterate to mark off consumed elements
242+ #[ doc( hidden) ]
243+ #[ inline]
244+ pub unsafe fn iter_position ( & mut self ) -> ( slice:: Iter < T > , & mut usize ) {
245+ ( self . array . iter ( ) , & mut self . position )
246+ }
208247}
209248
210249impl < T , N : ArrayLength < T > > Drop for ArrayConsumer < T , N > {
211250 fn drop ( & mut self ) {
212- for i in self . position ..N :: to_usize ( ) {
251+ for value in & mut self . array [ self . position ..N :: to_usize ( ) ] {
213252 unsafe {
214- ptr:: drop_in_place ( self . array . get_unchecked_mut ( i ) ) ;
253+ ptr:: drop_in_place ( value ) ;
215254 }
216255 }
217256 }
@@ -249,21 +288,25 @@ where
249288 where
250289 I : IntoIterator < Item = T > ,
251290 {
252- let mut destination = ArrayBuilder :: new ( ) ;
291+ unsafe {
292+ let mut destination = ArrayBuilder :: new ( ) ;
253293
254- for ( src, dst) in iter. into_iter ( ) . zip ( destination. array . iter_mut ( ) ) {
255- unsafe {
256- ptr:: write ( dst, src) ;
294+ {
295+ let ( destination_iter, position) = destination. iter_position ( ) ;
296+
297+ for ( src, dst) in iter. into_iter ( ) . zip ( destination_iter) {
298+ ptr:: write ( dst, src) ;
299+
300+ * position += 1 ;
301+ }
257302 }
258303
259- destination. position += 1 ;
260- }
304+ if destination. position < N :: to_usize ( ) {
305+ from_iter_length_fail ( destination. position , N :: to_usize ( ) ) ;
306+ }
261307
262- if destination. position < N :: to_usize ( ) {
263- from_iter_length_fail ( destination. position , N :: to_usize ( ) ) ;
308+ destination. into_inner ( )
264309 }
265-
266- destination. into_inner ( )
267310 }
268311}
269312
@@ -288,17 +331,21 @@ where
288331 where
289332 F : FnMut ( usize ) -> T ,
290333 {
291- let mut destination = ArrayBuilder :: new ( ) ;
334+ unsafe {
335+ let mut destination = ArrayBuilder :: new ( ) ;
292336
293- for ( i, dst) in destination. array . iter_mut ( ) . enumerate ( ) {
294- unsafe {
295- ptr:: write ( dst, f ( i) ) ;
337+ {
338+ let ( destination_iter, position) = destination. iter_position ( ) ;
339+
340+ for ( i, dst) in destination_iter. enumerate ( ) {
341+ ptr:: write ( dst, f ( i) ) ;
342+
343+ * position += 1 ;
344+ }
296345 }
297346
298- destination. position += 1 ;
347+ destination. into_inner ( )
299348 }
300-
301- destination. into_inner ( )
302349 }
303350
304351 #[ doc( hidden) ]
@@ -314,27 +361,23 @@ where
314361 Self :: Length : ArrayLength < B > + ArrayLength < U > ,
315362 F : FnMut ( B , Self :: Item ) -> U ,
316363 {
317- let mut left = ArrayConsumer :: new ( lhs) ;
318- let mut right = ArrayConsumer :: new ( self ) ;
319-
320- let ArrayConsumer {
321- array : ref left_array,
322- position : ref mut left_position,
323- } = left;
324- let ArrayConsumer {
325- array : ref right_array,
326- position : ref mut right_position,
327- } = right;
328-
329- FromIterator :: from_iter ( left_array. iter ( ) . zip ( right_array. iter ( ) ) . map ( |( l, r) | {
330- let left_value = unsafe { ptr:: read ( l) } ;
331- let right_value = unsafe { ptr:: read ( r) } ;
332-
333- * left_position += 1 ;
334- * right_position += 1 ;
335-
336- f ( left_value, right_value)
337- } ) )
364+ unsafe {
365+ let mut left = ArrayConsumer :: new ( lhs) ;
366+ let mut right = ArrayConsumer :: new ( self ) ;
367+
368+ let ( left_array_iter, left_position) = left. iter_position ( ) ;
369+ let ( right_array_iter, right_position) = right. iter_position ( ) ;
370+
371+ FromIterator :: from_iter ( left_array_iter. zip ( right_array_iter) . map ( |( l, r) | {
372+ let left_value = ptr:: read ( l) ;
373+ let right_value = ptr:: read ( r) ;
374+
375+ * left_position += 1 ;
376+ * right_position += 1 ;
377+
378+ f ( left_value, right_value)
379+ } ) )
380+ }
338381 }
339382
340383 #[ doc( hidden) ]
@@ -345,24 +388,23 @@ where
345388 Self :: Length : ArrayLength < B > + ArrayLength < U > ,
346389 F : FnMut ( Lhs :: Item , Self :: Item ) -> U ,
347390 {
348- let mut right = ArrayConsumer :: new ( self ) ;
391+ unsafe {
392+ let mut right = ArrayConsumer :: new ( self ) ;
349393
350- let ArrayConsumer {
351- array : ref right_array,
352- position : ref mut right_position,
353- } = right;
394+ let ( right_array_iter, right_position) = right. iter_position ( ) ;
354395
355- FromIterator :: from_iter (
356- lhs. into_iter ( )
357- . zip ( right_array . iter ( ) )
358- . map ( |( left_value, r) | {
359- let right_value = unsafe { ptr:: read ( r) } ;
396+ FromIterator :: from_iter (
397+ lhs. into_iter ( )
398+ . zip ( right_array_iter )
399+ . map ( |( left_value, r) | {
400+ let right_value = ptr:: read ( r) ;
360401
361- * right_position += 1 ;
402+ * right_position += 1 ;
362403
363- f ( left_value, right_value)
364- } ) ,
365- )
404+ f ( left_value, right_value)
405+ } ) ,
406+ )
407+ }
366408 }
367409}
368410
@@ -385,20 +427,19 @@ where
385427 Self : MappedGenericSequence < T , U > ,
386428 F : FnMut ( T ) -> U ,
387429 {
388- let mut source = ArrayConsumer :: new ( self ) ;
430+ unsafe {
431+ let mut source = ArrayConsumer :: new ( self ) ;
389432
390- let ArrayConsumer {
391- ref array,
392- ref mut position,
393- } = source;
433+ let ( array_iter, position) = source. iter_position ( ) ;
394434
395- FromIterator :: from_iter ( array . iter ( ) . map ( |src| {
396- let value = unsafe { ptr:: read ( src) } ;
435+ FromIterator :: from_iter ( array_iter . map ( |src| {
436+ let value = ptr:: read ( src) ;
397437
398- * position += 1 ;
438+ * position += 1 ;
399439
400- f ( value)
401- } ) )
440+ f ( value)
441+ } ) )
442+ }
402443 }
403444
404445 #[ inline]
@@ -417,20 +458,19 @@ where
417458 where
418459 F : FnMut ( U , T ) -> U ,
419460 {
420- let mut source = ArrayConsumer :: new ( self ) ;
461+ unsafe {
462+ let mut source = ArrayConsumer :: new ( self ) ;
421463
422- let ArrayConsumer {
423- ref array,
424- ref mut position,
425- } = source;
464+ let ( array_iter, position) = source. iter_position ( ) ;
426465
427- array . iter ( ) . fold ( init, |acc, src| {
428- let value = unsafe { ptr:: read ( src) } ;
466+ array_iter . fold ( init, |acc, src| {
467+ let value = ptr:: read ( src) ;
429468
430- * position += 1 ;
469+ * position += 1 ;
431470
432- f ( acc, value)
433- } )
471+ f ( acc, value)
472+ } )
473+ }
434474 }
435475}
436476
@@ -520,17 +560,21 @@ where
520560 let iter = iter. into_iter ( ) ;
521561
522562 if iter. len ( ) == N :: to_usize ( ) {
523- let mut destination = ArrayBuilder :: new ( ) ;
563+ unsafe {
564+ let mut destination = ArrayBuilder :: new ( ) ;
524565
525- for ( dst, src) in destination. array . iter_mut ( ) . zip ( iter. into_iter ( ) ) {
526- unsafe {
527- ptr:: write ( dst, src) ;
566+ {
567+ let ( destination_iter, position) = destination. iter_position ( ) ;
568+
569+ for ( dst, src) in destination_iter. zip ( iter. into_iter ( ) ) {
570+ ptr:: write ( dst, src) ;
571+
572+ * position += 1 ;
573+ }
528574 }
529575
530- destination. position += 1 ;
576+ Some ( destination. into_inner ( ) )
531577 }
532-
533- Some ( destination. into_inner ( ) )
534578 } else {
535579 None
536580 }
0 commit comments