@@ -16,7 +16,7 @@ use crate::mem::{self, MaybeUninit};
16
16
use crate :: ops:: {
17
17
ChangeOutputType , ControlFlow , FromResidual , Index , IndexMut , NeverShortCircuit , Residual , Try ,
18
18
} ;
19
- use crate :: ptr:: { null, null_mut} ;
19
+ use crate :: ptr:: { copy_nonoverlapping , null, null_mut} ;
20
20
use crate :: slice:: { Iter , IterMut } ;
21
21
22
22
mod ascii;
@@ -154,6 +154,44 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T; 1] {
154
154
unsafe { & mut * ( s as * mut T ) . cast :: < [ T ; 1 ] > ( ) }
155
155
}
156
156
157
+ /// Tries to create an array `[T; N]` by copying from a slice `&[T]`.
158
+ /// Succeeds if `slice.len() == N`.
159
+ ///
160
+ /// # Example
161
+ ///
162
+ /// ```
163
+ /// #![feature(array_try_from_slice)]
164
+ ///
165
+ /// use core::array;
166
+ ///
167
+ /// let data = array::try_from_slice(&[255, 127, 63, 31]).unwrap();
168
+ ///
169
+ /// let value = u32::from_le_bytes(data);
170
+ /// assert_eq!(value, 0x1F3F7FFF);
171
+ /// ```
172
+ #[ inline]
173
+ #[ unstable( feature = "array_try_from_slice" , issue = "133440" ) ]
174
+ #[ rustc_const_unstable( feature = "array_try_from_slice" , issue = "133440" ) ]
175
+ pub const fn try_from_slice < T , const N : usize > ( slice : & [ T ] ) -> Result < [ T ; N ] , TryFromSliceError >
176
+ where
177
+ T : Copy ,
178
+ {
179
+ if slice. len ( ) == N {
180
+ // SAFETY: `MaybeUninit` always supports being in an unitialised state, even as an array.
181
+ let mut me: [ MaybeUninit < T > ; N ] = unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) } ;
182
+
183
+ // SAFETY: `me` and `slice` are both exclusive as the former is a mutable reference. They also both contain `N` elements. `T` additionally implements `Copy`.
184
+ unsafe { copy_nonoverlapping ( slice. as_ptr ( ) , me. as_mut_ptr ( ) as * mut T , N ) } ;
185
+
186
+ // SAFETY: `MaybeUninit<T>` is transparent to `T`, and every item has also been initialised.
187
+ let me = unsafe { transmute_unchecked ( me) } ;
188
+
189
+ Ok ( me)
190
+ } else {
191
+ Err ( TryFromSliceError ( ( ) ) )
192
+ }
193
+ }
194
+
157
195
/// The error type returned when a conversion from a slice to an array fails.
158
196
#[ stable( feature = "try_from" , since = "1.34.0" ) ]
159
197
#[ rustc_allowed_through_unstable_modules]
@@ -214,8 +252,8 @@ impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
214
252
}
215
253
}
216
254
217
- /// Tries to create an array `[T; N]` by copying from a slice `&[T]`. Succeeds if
218
- /// `slice.len() == N`.
255
+ /// Tries to create an array `[T; N]` by copying from a slice `&[T]`.
256
+ /// Succeeds if `slice.len() == N`.
219
257
///
220
258
/// ```
221
259
/// let bytes: [u8; 3] = [1, 0, 2];
@@ -235,7 +273,7 @@ where
235
273
236
274
#[ inline]
237
275
fn try_from ( slice : & [ T ] ) -> Result < [ T ; N ] , TryFromSliceError > {
238
- < & Self > :: try_from ( slice) . copied ( )
276
+ try_from_slice ( slice)
239
277
}
240
278
}
241
279
@@ -260,7 +298,7 @@ where
260
298
261
299
#[ inline]
262
300
fn try_from ( slice : & mut [ T ] ) -> Result < [ T ; N ] , TryFromSliceError > {
263
- < Self > :: try_from ( & * slice)
301
+ try_from_slice ( slice)
264
302
}
265
303
}
266
304
0 commit comments