Skip to content

Commit 3eb0f68

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

File tree

1 file changed

+41
-5
lines changed

1 file changed

+41
-5
lines changed

library/core/src/array/mod.rs

+41-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,42 @@ 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+
/// 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+
157193
/// The error type returned when a conversion from a slice to an array fails.
158194
#[stable(feature = "try_from", since = "1.34.0")]
159195
#[rustc_allowed_through_unstable_modules]
@@ -214,8 +250,8 @@ impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
214250
}
215251
}
216252

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`.
219255
///
220256
/// ```
221257
/// let bytes: [u8; 3] = [1, 0, 2];
@@ -235,7 +271,7 @@ where
235271

236272
#[inline]
237273
fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
238-
<&Self>::try_from(slice).copied()
274+
try_from_slice(slice)
239275
}
240276
}
241277

@@ -260,7 +296,7 @@ where
260296

261297
#[inline]
262298
fn try_from(slice: &mut [T]) -> Result<[T; N], TryFromSliceError> {
263-
<Self>::try_from(&*slice)
299+
try_from_slice(slice)
264300
}
265301
}
266302

0 commit comments

Comments
 (0)