Skip to content

Commit 03c4be7

Browse files
authored
Add Array::slice_as_(mut_)array (#171)
Equivalent of core `[T]::as_(mut_)array`. Effectively a `const fn` equivalent of `TryFrom<&[T]> for Array<T, U>` (and `mut` equivalent).
1 parent a202541 commit 03c4be7

2 files changed

Lines changed: 84 additions & 33 deletions

File tree

src/lib.rs

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,39 @@ where
292292
}
293293
}
294294

295+
/// Get a reference to an array from a slice, if the slice is exactly the size of the array.
296+
///
297+
/// Returns `None` if the slice's length is not exactly equal to the array size.
298+
#[inline]
299+
#[must_use]
300+
pub const fn slice_as_array(slice: &[T]) -> Option<&Self> {
301+
if slice.len() == U::USIZE {
302+
// SAFETY: `Self` is ensured to be layout-identical to `[T; U::USIZE]`, and immediately
303+
// above we validated that `slice` is also layout-identical to `[T; U::USIZE]`,
304+
// therefore the cast is valid.
305+
unsafe { Some(&*slice.as_ptr().cast()) }
306+
} else {
307+
None
308+
}
309+
}
310+
311+
/// Get a mutable reference to an array from a slice, if the slice is exactly the size of the
312+
/// array.
313+
///
314+
/// Returns `None` if the slice's length is not exactly equal to the array size.
315+
#[inline]
316+
#[must_use]
317+
pub const fn slice_as_mut_array(slice: &mut [T]) -> Option<&mut Self> {
318+
if slice.len() == U::USIZE {
319+
// SAFETY: `Self` is ensured to be layout-identical to `[T; U::USIZE]`, and immediately
320+
// above we validated that `slice` is also layout-identical to `[T; U::USIZE]`,
321+
// therefore the cast is valid.
322+
unsafe { Some(&mut *slice.as_mut_ptr().cast()) }
323+
} else {
324+
None
325+
}
326+
}
327+
295328
/// Splits the shared slice into a slice of `U`-element arrays, starting at the beginning
296329
/// of the slice, and a remainder slice with length strictly less than `U`.
297330
///
@@ -883,6 +916,38 @@ unsafe impl<T, U: ArraySize> Send for Array<T, U> where T: Send {}
883916
/// also be `Sync`.
884917
unsafe impl<T, U: ArraySize> Sync for Array<T, U> where T: Sync {}
885918

919+
impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
920+
where
921+
U: ArraySize,
922+
{
923+
type Error = TryFromSliceError;
924+
925+
#[inline]
926+
fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
927+
check_slice_length::<T, U>(slice)?;
928+
929+
// SAFETY: `Array<T, U>` is a `repr(transparent)` newtype for a core
930+
// array with length checked above.
931+
Ok(unsafe { &*slice.as_ptr().cast() })
932+
}
933+
}
934+
935+
impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
936+
where
937+
U: ArraySize,
938+
{
939+
type Error = TryFromSliceError;
940+
941+
#[inline]
942+
fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
943+
check_slice_length::<T, U>(slice)?;
944+
945+
// SAFETY: `Array<T, U>` is a `repr(transparent)` newtype for a core
946+
// array with length checked above.
947+
Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
948+
}
949+
}
950+
886951
impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
887952
where
888953
Self: Clone,
@@ -952,38 +1017,6 @@ where
9521017
}
9531018
}
9541019

955-
impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
956-
where
957-
U: ArraySize,
958-
{
959-
type Error = TryFromSliceError;
960-
961-
#[inline]
962-
fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
963-
check_slice_length::<T, U>(slice)?;
964-
965-
// SAFETY: `Array<T, U>` is a `repr(transparent)` newtype for a core
966-
// array with length checked above.
967-
Ok(unsafe { &*slice.as_ptr().cast() })
968-
}
969-
}
970-
971-
impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
972-
where
973-
U: ArraySize,
974-
{
975-
type Error = TryFromSliceError;
976-
977-
#[inline]
978-
fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
979-
check_slice_length::<T, U>(slice)?;
980-
981-
// SAFETY: `Array<T, U>` is a `repr(transparent)` newtype for a core
982-
// array with length checked above.
983-
Ok(unsafe { &mut *slice.as_mut_ptr().cast() })
984-
}
985-
}
986-
9871020
// Deprecated legacy methods to ease migrations from `generic-array`
9881021
impl<T, U> Array<T, U>
9891022
where

tests/mod.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const EXAMPLE_SLICE: &[u8] = &[1, 2, 3, 4, 5, 6];
1010
const _FOO: ArrayN<u8, 4> = Array([1, 2, 3, 4]);
1111

1212
#[test]
13-
fn tryfrom_slice_for_array() {
13+
fn tryfrom_slice_for_clonable_array() {
1414
assert!(Array::<u8, U0>::try_from(EXAMPLE_SLICE).is_err());
1515
assert!(Array::<u8, U3>::try_from(EXAMPLE_SLICE).is_err());
1616

@@ -31,6 +31,24 @@ fn tryfrom_slice_for_array_ref() {
3131
assert!(<&Array::<u8, U7>>::try_from(EXAMPLE_SLICE).is_err());
3232
}
3333

34+
#[test]
35+
fn slice_as_array() {
36+
type A = Array<u8, U2>;
37+
assert_eq!(A::slice_as_array(&[]), None);
38+
assert_eq!(A::slice_as_array(&[1]), None);
39+
assert_eq!(A::slice_as_array(&[1, 2]), Some(&Array([1, 2])));
40+
assert_eq!(A::slice_as_array(&[1, 2, 3]), None);
41+
}
42+
43+
#[test]
44+
fn slice_as_mut_array() {
45+
type A = Array<u8, U2>;
46+
assert_eq!(A::slice_as_mut_array(&mut []), None);
47+
assert_eq!(A::slice_as_mut_array(&mut [1]), None);
48+
assert_eq!(A::slice_as_mut_array(&mut [1, 2]), Some(&mut Array([1, 2])));
49+
assert_eq!(A::slice_as_mut_array(&mut [1, 2, 3]), None);
50+
}
51+
3452
#[test]
3553
fn concat() {
3654
let prefix = Array::<u8, U2>::try_from(&EXAMPLE_SLICE[..2]).unwrap();

0 commit comments

Comments
 (0)