@@ -11,7 +11,9 @@ use crate::cmp::Ordering;
1111use crate :: convert:: { Infallible , TryFrom } ;
1212use crate :: fmt;
1313use crate :: hash:: { self , Hash } ;
14+ use crate :: iter:: FromIterator ;
1415use crate :: marker:: Unsize ;
16+ use crate :: mem:: MaybeUninit ;
1517use crate :: slice:: { Iter , IterMut } ;
1618
1719mod iter;
@@ -174,6 +176,103 @@ impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N] {
174176 }
175177}
176178
179+ /// Return Error of the FromIterator impl for array
180+ #[ unstable( feature = "array_from_iter_impl" , issue = "none" ) ]
181+ pub struct FillError < T , const N : usize > {
182+ array : [ MaybeUninit < T > ; N ] ,
183+ len : usize ,
184+ }
185+
186+ #[ unstable( feature = "array_from_iter_impl" , issue = "none" ) ]
187+ impl < T , const N : usize > fmt:: Display for FillError < T , N > {
188+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
189+ fmt:: Display :: fmt (
190+ & format_args ! ( "The iterator only returned {} items, but {} were needed" , self . len( ) , N ) ,
191+ f,
192+ )
193+ }
194+ }
195+
196+ #[ unstable( feature = "array_from_iter_impl" , issue = "none" ) ]
197+ impl < T : fmt:: Debug , const N : usize > fmt:: Debug for FillError < T , N > {
198+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
199+ f. debug_struct ( "FillError" )
200+ . field ( "array" , & self . as_slice ( ) )
201+ . field ( "len" , & self . len ( ) )
202+ . finish ( )
203+ }
204+ }
205+
206+ #[ unstable( feature = "array_from_iter_impl" , issue = "none" ) ]
207+ impl < T , const N : usize > Drop for FillError < T , N > {
208+ fn drop ( & mut self ) {
209+ // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
210+ // of elements that have been initialized and need to be droped
211+ unsafe { crate :: ptr:: drop_in_place ( self . as_mut_slice ( ) ) }
212+ }
213+ }
214+
215+ #[ unstable( feature = "array_from_iter_impl" , issue = "none" ) ]
216+ impl < T , const N : usize > FillError < T , N > {
217+ fn new ( ) -> Self {
218+ Self { array : MaybeUninit :: uninit_array ( ) , len : 0 }
219+ }
220+
221+ /// Returns how many elements were read from the given iterator.
222+ pub fn len ( & self ) -> usize {
223+ self . len
224+ }
225+
226+ /// Returns an immutable slice of all initialized elements.
227+ pub fn as_slice ( & self ) -> & [ T ] {
228+ // SAFETY: We know that all elements from 0 to len are properly initialized.
229+ unsafe { MaybeUninit :: slice_get_ref ( & self . array [ 0 ..self . len ] ) }
230+ }
231+
232+ /// Returns a mutable slice of all initialized elements.
233+ pub fn as_mut_slice ( & mut self ) -> & mut [ T ] {
234+ // SAFETY: We know that all elements from 0 to len are properly initialized.
235+ unsafe { MaybeUninit :: slice_get_mut ( & mut self . array [ 0 ..self . len ] ) }
236+ }
237+
238+ /// Tries to initialize the left-over elements using `iter`.
239+ pub fn fill < I : IntoIterator < Item = T > > ( mut self , iter : I ) -> Result < [ T ; N ] , FillError < T , N > > {
240+ let mut iter = iter. into_iter ( ) ;
241+
242+ for i in self . len ..N {
243+ if let Some ( value) = iter. next ( ) {
244+ self . array [ i] . write ( value) ;
245+ } else {
246+ self . len = i;
247+ return Err ( self ) ;
248+ }
249+ }
250+
251+ // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
252+ // promise:
253+ //
254+ // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
255+ // > as `T`.
256+ //
257+ // The docs even show a transmute from an array of `MaybeUninit<T>` to
258+ // an array of `T`.
259+ //
260+ // With that, this initialization satisfies the invariants.
261+ // FIXME: actually use `mem::transmute` here, once it
262+ // works with const generics:
263+ // `mem::transmute::<[MaybeUninit<T>; N], [T; N]>(array)`
264+ Ok ( unsafe { crate :: ptr:: read ( & self . array as * const [ MaybeUninit < T > ; N ] as * const [ T ; N ] ) } )
265+ }
266+ }
267+
268+ #[ unstable( feature = "array_from_iter_impl" , issue = "none" ) ]
269+ impl < T , const N : usize > FromIterator < T > for Result < [ T ; N ] , FillError < T , N > > {
270+ #[ inline]
271+ fn from_iter < I : IntoIterator < Item = T > > ( iter : I ) -> Self {
272+ FillError :: < T , N > :: new ( ) . fill ( iter)
273+ }
274+ }
275+
177276#[ stable( feature = "rust1" , since = "1.0.0" ) ]
178277impl < ' a , T , const N : usize > IntoIterator for & ' a [ T ; N ] {
179278 type Item = & ' a T ;
0 commit comments