Skip to content

Commit

Permalink
hybrid-array: add slice cast methods to ArrayOps (#1038)
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov committed Jan 10, 2024
1 parent 4766588 commit cdc6acd
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 8 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions hybrid-array/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ where
T: Clone,
U: ArraySize,
{
#[inline]
fn clone(&self) -> Self {
Self::from_fn(|n| self.0.as_ref()[n].clone())
}
Expand Down Expand Up @@ -319,6 +320,7 @@ where
T: Default,
U: ArraySize,
{
#[inline]
fn default() -> Self {
Self::from_fn(|_| Default::default())
}
Expand Down Expand Up @@ -464,6 +466,7 @@ where
/// Creates a consuming iterator, that is, one that moves each value out of
/// the array (from start to end). The array cannot be used after calling
/// this unless `T` implements `Copy`, so the whole array is copied.
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
Expand All @@ -476,6 +479,7 @@ where
type Item = &'a T;
type IntoIter = Iter<'a, T>;

#[inline]
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
Expand All @@ -499,6 +503,7 @@ where
T: PartialEq,
U: ArraySize,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.0.as_ref().eq(other.0.as_ref())
}
Expand All @@ -509,6 +514,7 @@ where
T: PartialEq,
U: ArraySize<ArrayType<T> = [T; N]>,
{
#[inline]
fn eq(&self, other: &[T; N]) -> bool {
self.0.eq(other)
}
Expand All @@ -519,6 +525,7 @@ where
T: PartialEq,
U: ArraySize<ArrayType<T> = [T; N]>,
{
#[inline]
fn eq(&self, other: &Array<T, U>) -> bool {
self.eq(&other.0)
}
Expand All @@ -529,6 +536,7 @@ where
T: PartialOrd,
U: ArraySize,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.as_ref().partial_cmp(other.0.as_ref())
}
Expand All @@ -539,6 +547,7 @@ where
T: Ord,
U: ArraySize,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.0.as_ref().cmp(other.0.as_ref())
}
Expand Down Expand Up @@ -595,6 +604,7 @@ where
T: Zeroize,
U: ArraySize,
{
#[inline]
fn zeroize(&mut self) {
self.0.as_mut().iter_mut().zeroize()
}
Expand Down Expand Up @@ -660,6 +670,18 @@ pub trait ArrayOps<T, const N: usize>:
fn map_to_core_array<F, U>(self, f: F) -> [U; N]
where
F: FnMut(T) -> U;

/// Transform slice to slice of core array type
fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]];

/// Transform mutable slice to mutable slice of core array type
fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]];

/// Transform slice to slice of core array type
fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self];

/// Transform mutable slice to mutable slice of core array type
fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self];
}

impl<T, const N: usize> ArrayOps<T, N> for [T; N] {
Expand Down Expand Up @@ -697,6 +719,26 @@ impl<T, const N: usize> ArrayOps<T, N> for [T; N] {
{
self.map(f)
}

#[inline]
fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
slice
}

#[inline]
fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; N]] {
slice
}

#[inline]
fn cast_slice_from_core(slice: &[[T; N]]) -> &[Self] {
slice
}

#[inline]
fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
slice
}
}

/// Slice operations which don't have access to a const generic array size.
Expand All @@ -713,13 +755,15 @@ pub trait SliceOps<T>:
/// Splits the shared slice into a slice of `N`-element arrays.
///
/// See [`slice_as_chunks`] for more information.
#[inline]
fn as_array_chunks<N: ArraySize>(&self) -> (&[Array<T, N>], &[T]) {
slice_as_chunks(self.as_ref())
}

/// Splits the exclusive slice into a slice of `N`-element arrays.
///
/// See [`slice_as_chunks_mut`] for more information.
#[inline]
fn as_array_chunks_mut<N: ArraySize>(&mut self) -> (&mut [Array<T, N>], &mut [T]) {
slice_as_chunks_mut(self.as_mut())
}
Expand Down Expand Up @@ -774,6 +818,7 @@ impl<T, U> FromFn<T> for Array<T, U>
where
U: ArraySize,
{
#[inline]
fn from_fn<F>(cb: F) -> Self
where
F: FnMut(usize) -> T,
Expand All @@ -783,6 +828,7 @@ where
}

impl<T, const N: usize> FromFn<T> for [T; N] {
#[inline]
fn from_fn<F>(cb: F) -> Self
where
F: FnMut(usize) -> T,
Expand All @@ -797,6 +843,7 @@ impl<T, const N: usize> FromFn<T> for [T; N] {
/// # Panics
/// Panics if `N` is 0.
#[allow(clippy::arithmetic_side_effects)]
#[inline]
pub fn slice_as_chunks<T, N: ArraySize>(buf: &[T]) -> (&[Array<T, N>], &[T]) {
assert_ne!(N::USIZE, 0, "chunk size must be non-zero");
// Arithmetic safety: we have checked that `N::USIZE` is not zero, thus
Expand All @@ -819,6 +866,7 @@ pub fn slice_as_chunks<T, N: ArraySize>(buf: &[T]) -> (&[Array<T, N>], &[T]) {
/// # Panics
/// Panics if `N` is 0.
#[allow(clippy::arithmetic_side_effects)]
#[inline]
pub fn slice_as_chunks_mut<T, N: ArraySize>(buf: &mut [T]) -> (&mut [Array<T, N>], &mut [T]) {
assert_ne!(N::USIZE, 0, "chunk size must be non-zero");
// Arithmetic safety: we have checked that `N::USIZE` is not zero, thus
Expand Down
24 changes: 24 additions & 0 deletions hybrid-array/src/sizes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,30 @@ macro_rules! impl_array_size {
{
self.0.map(f)
}

#[inline]
fn cast_slice_to_core(slice: &[Self]) -> &[[T; $len]] {
// SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]`
unsafe { core::slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
}

#[inline]
fn cast_slice_to_core_mut(slice: &mut [Self]) -> &mut [[T; $len]] {
// SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]`
unsafe { core::slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
}

#[inline]
fn cast_slice_from_core(slice: &[[T; $len]]) -> &[Self] {
// SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]`
unsafe { core::slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
}

#[inline]
fn cast_slice_from_core_mut(slice: &mut [[T; $len]]) -> &mut [Self] {
// SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]`
unsafe { core::slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
}
}
)+
};
Expand Down

0 comments on commit cdc6acd

Please sign in to comment.