@@ -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,42 @@ 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
+ /// use core::array;
164
+ ///
165
+ /// let data = array::try_from_slice(&[255, 127, 63, 31]).unwrap();
166
+ ///
167
+ /// let value = u32::from_le_bytes(data);
168
+ /// assert_eq!(value, 0x1F3F7FFF);
169
+ /// ```
170
+ #[ inline]
171
+ #[ unstable( feature = "array_try_from_slice" , issue = "133440" ) ]
172
+ #[ rustc_const_unstable( feature = "array_try_from_slice" , issue = "133440" ) ]
173
+ pub const fn try_from_slice < T , const N : usize > ( slice : & [ T ] ) -> Result < [ T ; N ] , TryFromSliceError >
174
+ where
175
+ T : Copy ,
176
+ {
177
+ if slice. len ( ) == N {
178
+ // SAFETY: `MaybeUninit` always supports being in an unitialised state, even as an array.
179
+ let mut me: [ MaybeUninit < T > ; N ] = unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) } ;
180
+
181
+ // SAFETY: `me` and `slice` are both exclusive as the former is a mutable reference. They also both contain `N` elements. `T` additionally implements `Copy`.
182
+ unsafe { copy_nonoverlapping ( slice. as_ptr ( ) , me. as_mut_ptr ( ) as * mut T , N ) } ;
183
+
184
+ // SAFETY: `MaybeUninit<T>` is transparent to `T`, and every item has also been initialised.
185
+ let me = unsafe { transmute_unchecked ( me) } ;
186
+
187
+ Ok ( me)
188
+ } else {
189
+ Err ( TryFromSliceError ( ( ) ) )
190
+ }
191
+ }
192
+
157
193
/// The error type returned when a conversion from a slice to an array fails.
158
194
#[ stable( feature = "try_from" , since = "1.34.0" ) ]
159
195
#[ rustc_allowed_through_unstable_modules]
@@ -214,8 +250,8 @@ impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
214
250
}
215
251
}
216
252
217
- /// Tries to create an array `[T; N]` by copying from a slice `&[T]`. Succeeds if
218
- /// `slice.len() == N`.
253
+ /// Tries to create an array `[T; N]` by copying from a slice `&[T]`.
254
+ /// Succeeds if `slice.len() == N`.
219
255
///
220
256
/// ```
221
257
/// let bytes: [u8; 3] = [1, 0, 2];
@@ -235,7 +271,7 @@ where
235
271
236
272
#[ inline]
237
273
fn try_from ( slice : & [ T ] ) -> Result < [ T ; N ] , TryFromSliceError > {
238
- < & Self > :: try_from ( slice) . copied ( )
274
+ try_from_slice ( slice)
239
275
}
240
276
}
241
277
@@ -260,7 +296,7 @@ where
260
296
261
297
#[ inline]
262
298
fn try_from ( slice : & mut [ T ] ) -> Result < [ T ; N ] , TryFromSliceError > {
263
- < Self > :: try_from ( & * slice)
299
+ try_from_slice ( slice)
264
300
}
265
301
}
266
302
0 commit comments