Skip to content

Commit 8d688b0

Browse files
committed
Add 'core::array::try_from_slice' constructor;
1 parent 67a8c64 commit 8d688b0

File tree

1 file changed

+43
-5
lines changed

1 file changed

+43
-5
lines changed

library/core/src/array/mod.rs

+43-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::mem::{self, MaybeUninit};
1616
use crate::ops::{
1717
ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try,
1818
};
19-
use crate::ptr::{null, null_mut};
19+
use crate::ptr::{copy_nonoverlapping, null, null_mut};
2020
use crate::slice::{Iter, IterMut};
2121

2222
mod ascii;
@@ -154,6 +154,44 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T; 1] {
154154
unsafe { &mut *(s as *mut T).cast::<[T; 1]>() }
155155
}
156156

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+
157195
/// The error type returned when a conversion from a slice to an array fails.
158196
#[stable(feature = "try_from", since = "1.34.0")]
159197
#[rustc_allowed_through_unstable_modules]
@@ -214,8 +252,8 @@ impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
214252
}
215253
}
216254

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`.
219257
///
220258
/// ```
221259
/// let bytes: [u8; 3] = [1, 0, 2];
@@ -235,7 +273,7 @@ where
235273

236274
#[inline]
237275
fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
238-
<&Self>::try_from(slice).copied()
276+
try_from_slice(slice)
239277
}
240278
}
241279

@@ -260,7 +298,7 @@ where
260298

261299
#[inline]
262300
fn try_from(slice: &mut [T]) -> Result<[T; N], TryFromSliceError> {
263-
<Self>::try_from(&*slice)
301+
try_from_slice(slice)
264302
}
265303
}
266304

0 commit comments

Comments
 (0)