Skip to content

Commit

Permalink
Revert "hybrid-array: get rid of check_slice_length (#1020)" (#1024)
Browse files Browse the repository at this point in the history
This reverts commit 49e9d68.

The extra bounds turn out to be rather problematic with e.g.
`crypto-common`, so revert this even though `check_slice_length` is a
hack.
  • Loading branch information
tarcieri authored Dec 31, 2023
1 parent 32a4aa5 commit 2bdcea1
Showing 1 changed file with 31 additions and 23 deletions.
54 changes: 31 additions & 23 deletions hybrid-array/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,7 @@ where
// TODO(tarcieri): deprecate this before the v0.2 release
// #[deprecated(since = "0.2.0", note = "use TryFrom instead")]
#[inline]
pub fn ref_from_slice<'a>(slice: &'a [T]) -> &'a Self
where
&'a Self: TryFrom<&'a [T], Error = TryFromSliceError>,
{
pub fn ref_from_slice(slice: &[T]) -> &Self {
slice.try_into().expect("slice length mismatch")
}

Expand All @@ -117,10 +114,7 @@ where
// TODO(tarcieri): deprecate this before the v0.2 release
// #[deprecated(since = "0.2.0", note = "use TryFrom instead")]
#[inline]
pub fn ref_from_mut_slice<'a>(slice: &'a mut [T]) -> &'a mut Self
where
&'a mut Self: TryFrom<&'a mut [T], Error = TryFromSliceError>,
{
pub fn ref_from_mut_slice(slice: &mut [T]) -> &mut Self {
slice.try_into().expect("slice length mismatch")
}

Expand All @@ -134,9 +128,9 @@ where
#[inline]
pub fn clone_from_slice(slice: &[T]) -> Self
where
T: Clone,
Self: Clone,
{
Self::from_fn(|n| slice[n].clone())
slice.try_into().expect("slice length mismatch")
}

/// Concatenates `self` with `other`.
Expand Down Expand Up @@ -508,10 +502,10 @@ where
}
}

impl<'a, T, U, const N: usize> TryFrom<&'a [T]> for Array<T, U>
impl<'a, T, U> TryFrom<&'a [T]> for Array<T, U>
where
Self: ArrayOps<T, N> + Clone,
U: ArraySize<ArrayType<T> = [T; N]>,
Self: Clone,
U: ArraySize,
{
type Error = TryFromSliceError;

Expand All @@ -521,37 +515,35 @@ where
}
}

impl<'a, T, U, const N: usize> TryFrom<&'a [T]> for &'a Array<T, U>
impl<'a, T, U> TryFrom<&'a [T]> for &'a Array<T, U>
where
Array<T, U>: ArrayOps<T, N>,
U: ArraySize<ArrayType<T> = [T; N]>,
U: ArraySize,
{
type Error = TryFromSliceError;

#[inline]
fn try_from(slice: &'a [T]) -> Result<Self, TryFromSliceError> {
let array_ref = <&'a [T; N]>::try_from(slice)?;
check_slice_length::<T, U>(slice)?;

// SAFETY: `Array<T, U>` is a `repr(transparent)` newtype for a core
// array with length checked above.
Ok(unsafe { &*(array_ref.as_ptr() as *const Array<T, U>) })
Ok(unsafe { &*(slice.as_ptr() as *const Array<T, U>) })
}
}

impl<'a, T, U, const N: usize> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array<T, U>
where
Array<T, U>: ArrayOps<T, N>,
U: ArraySize<ArrayType<T> = [T; N]>,
U: ArraySize,
{
type Error = TryFromSliceError;

#[inline]
fn try_from(slice: &'a mut [T]) -> Result<Self, TryFromSliceError> {
let array_ref = <&'a mut [T; N]>::try_from(slice)?;
check_slice_length::<T, U>(slice)?;

// SAFETY: `Array<T, U>` is a `repr(transparent)` newtype for a core
// array with length checked above.
Ok(unsafe { &mut *(array_ref.as_ptr() as *mut Array<T, U>) })
Ok(unsafe { &mut *(slice.as_ptr() as *mut Array<T, U>) })
}
}

Expand All @@ -574,6 +566,22 @@ where
{
}

/// Generate a [`TryFromSliceError`] if the slice doesn't match the given length.
#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))]
fn check_slice_length<T, U: ArraySize>(slice: &[T]) -> Result<(), TryFromSliceError> {
debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE);

if slice.len() != U::USIZE {
// Hack: `TryFromSliceError` lacks a public constructor
<&[T; 1]>::try_from([].as_slice())?;

#[cfg(debug_assertions)]
unreachable!();
}

Ok(())
}

/// Array operations which are const generic over a given array size.
pub trait ArrayOps<T, const N: usize>:
Borrow<[T; N]>
Expand Down

0 comments on commit 2bdcea1

Please sign in to comment.