Skip to content

Commit

Permalink
Remove ArrayOps and SliceOps
Browse files Browse the repository at this point in the history
After #24, #25, and #26, these traits don't really need to exist and
have largely been replaced by safe type conversions with appropriate
bounds.

In lieu of `ArrayOps<T, N>` we instead can use
`U: ArraySize<ArrayType<T> = [T; N]>>` as a bound, which albeit a bit
more verbose concretely describes the inner type of `Array` to the
compiler.

The `cast_slice_(to|from)_core(_mut)` methods previously defined on the
trait have been preserved, but as static methods of `Array`, making the
change largely a drop in replacement. Places where they were being
called as e.g. `ArrayOps::cast_slice_to_core` just need to be called as
`Array::cast_slice_to_core` instead.
  • Loading branch information
tarcieri committed Jan 27, 2024
1 parent ca926e4 commit 84ed607
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 139 deletions.
34 changes: 34 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,40 @@ where
}
}

// Impls which depend on the inner array type being `[T; N]`.
impl<T, U, const N: usize> Array<T, U>
where
U: ArraySize<ArrayType<T> = [T; N]>,
{
/// Transform slice to slice of core array type.
#[inline]
pub fn cast_slice_to_core(slice: &[Self]) -> &[[T; N]] {
// SAFETY: `Self` is a `repr(transparent)` newtype for `[T; N]`
unsafe { core::slice::from_raw_parts(slice.as_ptr().cast(), slice.len()) }
}

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

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

/// Transform mutable slice to mutable slice of core array type.
#[inline]
pub fn cast_slice_from_core_mut(slice: &mut [[T; N]]) -> &mut [Self] {
// SAFETY: `Self` is a `repr(transparent)` newtype for `[T; N]`
unsafe { core::slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), slice.len()) }
}
}

impl<T, U, const N: usize> Array<MaybeUninit<T>, U>
where
U: ArraySize<ArrayType<MaybeUninit<T>> = [MaybeUninit<T>; N]>,
Expand Down
38 changes: 1 addition & 37 deletions src/sizes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Macros for defining various array sizes, and their associated invocations.

use super::{Array, ArrayOps, ArraySize, AssociatedArraySize};
use super::{ArraySize, AssociatedArraySize};

macro_rules! impl_array_size {
($($len:expr => $ty:ident),+) => {
Expand All @@ -12,42 +12,6 @@ macro_rules! impl_array_size {
impl<T> AssociatedArraySize for [T; $len] {
type Size = typenum::$ty;
}

impl<T> ArrayOps<T, $len> for Array<T, typenum::$ty> {
const SIZE: usize = $len;

#[inline]
fn map_to_core_array<F, U>(self, f: F) -> [U; $len]
where
F: FnMut(T) -> U
{
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
112 changes: 10 additions & 102 deletions src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Trait definitions.

use crate::{slice_as_chunks, slice_as_chunks_mut, Array, FromFn};
use crate::{Array, FromFn};
use core::{
borrow::{Borrow, BorrowMut},
ops::{Index, IndexMut, Range},
Expand All @@ -23,11 +23,18 @@ pub unsafe trait ArraySize: Unsigned {
/// This is always defined to be `[T; N]` where `N` is the same as
/// [`ArraySize::USIZE`][`typenum::Unsigned::USIZE`].
type ArrayType<T>: AssociatedArraySize<Size = Self>
+ AsRef<[T]>
+ AsMut<[T]>
+ Borrow<[T]>
+ BorrowMut<[T]>
+ From<Array<T, Self>>
+ FromFn<T>
+ Index<usize>
+ Index<Range<usize>>
+ IndexMut<usize>
+ IndexMut<Range<usize>>
+ Into<Array<T, Self>>
+ IntoIterator<Item = T>
+ SliceOps<T>;
+ IntoIterator<Item = T>;
}

/// Associates an [`ArraySize`] with a given type.
Expand All @@ -42,102 +49,3 @@ where
{
type Size = U;
}

/// Array operations which are const generic over a given array size.
pub trait ArrayOps<T, const N: usize>:
Borrow<[T; N]>
+ BorrowMut<[T; N]>
+ From<[T; N]>
+ FromFn<T>
+ Into<[T; N]>
+ IntoIterator<Item = T>
+ Sized
+ SliceOps<T>
{
/// Size of an array as a `usize`.
///
/// Not to be confused with [`AssociatedArraySize::Size`], which is [`typenum`]-based.
const SIZE: usize;

/// Returns an array of the same size as `self`, with function `f` applied to each element
/// in order.
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] {
const SIZE: usize = N;

#[inline]
fn map_to_core_array<F, U>(self, f: F) -> [U; N]
where
F: FnMut(T) -> U,
{
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.
pub trait SliceOps<T>:
AsRef<[T]>
+ AsMut<[T]>
+ Borrow<[T]>
+ BorrowMut<[T]>
+ Index<usize>
+ Index<Range<usize>>
+ IndexMut<usize>
+ IndexMut<Range<usize>>
{
/// 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())
}
}

impl<T> SliceOps<T> for [T] {}
impl<T, const N: usize> SliceOps<T> for [T; N] {}
impl<T, U: ArraySize> SliceOps<T> for Array<T, U> {}

0 comments on commit 84ed607

Please sign in to comment.