@@ -11,7 +11,9 @@ use crate::cmp::Ordering;
11
11
use crate :: convert:: { Infallible , TryFrom } ;
12
12
use crate :: fmt;
13
13
use crate :: hash:: { self , Hash } ;
14
+ use crate :: iter:: FromIterator ;
14
15
use crate :: marker:: Unsize ;
16
+ use crate :: mem:: MaybeUninit ;
15
17
use crate :: slice:: { Iter , IterMut } ;
16
18
17
19
mod iter;
@@ -174,6 +176,103 @@ impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N] {
174
176
}
175
177
}
176
178
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
+
177
276
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
178
277
impl < ' a , T , const N : usize > IntoIterator for & ' a [ T ; N ] {
179
278
type Item = & ' a T ;
0 commit comments