From cdc6acde10aa02016d79d26d0dc97faa80ecf4a6 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 10 Jan 2024 19:07:07 +0300 Subject: [PATCH] hybrid-array: add slice cast methods to ArrayOps (#1038) --- Cargo.lock | 16 ++++++------- hybrid-array/src/lib.rs | 48 +++++++++++++++++++++++++++++++++++++++ hybrid-array/src/sizes.rs | 24 ++++++++++++++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03388672..02639446 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,9 +115,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "opaque-debug" @@ -135,9 +135,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.75" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -159,18 +159,18 @@ checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "serde" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index d94ab7c0..ae14a80f 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -291,6 +291,7 @@ where T: Clone, U: ArraySize, { + #[inline] fn clone(&self) -> Self { Self::from_fn(|n| self.0.as_ref()[n].clone()) } @@ -319,6 +320,7 @@ where T: Default, U: ArraySize, { + #[inline] fn default() -> Self { Self::from_fn(|_| Default::default()) } @@ -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() } @@ -476,6 +479,7 @@ where type Item = &'a T; type IntoIter = Iter<'a, T>; + #[inline] fn into_iter(self) -> Iter<'a, T> { self.iter() } @@ -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()) } @@ -509,6 +514,7 @@ where T: PartialEq, U: ArraySize = [T; N]>, { + #[inline] fn eq(&self, other: &[T; N]) -> bool { self.0.eq(other) } @@ -519,6 +525,7 @@ where T: PartialEq, U: ArraySize = [T; N]>, { + #[inline] fn eq(&self, other: &Array) -> bool { self.eq(&other.0) } @@ -529,6 +536,7 @@ where T: PartialOrd, U: ArraySize, { + #[inline] fn partial_cmp(&self, other: &Self) -> Option { self.0.as_ref().partial_cmp(other.0.as_ref()) } @@ -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()) } @@ -595,6 +604,7 @@ where T: Zeroize, U: ArraySize, { + #[inline] fn zeroize(&mut self) { self.0.as_mut().iter_mut().zeroize() } @@ -660,6 +670,18 @@ pub trait ArrayOps: fn map_to_core_array(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 ArrayOps for [T; N] { @@ -697,6 +719,26 @@ impl ArrayOps 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. @@ -713,6 +755,7 @@ pub trait SliceOps: /// Splits the shared slice into a slice of `N`-element arrays. /// /// See [`slice_as_chunks`] for more information. + #[inline] fn as_array_chunks(&self) -> (&[Array], &[T]) { slice_as_chunks(self.as_ref()) } @@ -720,6 +763,7 @@ pub trait SliceOps: /// 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(&mut self) -> (&mut [Array], &mut [T]) { slice_as_chunks_mut(self.as_mut()) } @@ -774,6 +818,7 @@ impl FromFn for Array where U: ArraySize, { + #[inline] fn from_fn(cb: F) -> Self where F: FnMut(usize) -> T, @@ -783,6 +828,7 @@ where } impl FromFn for [T; N] { + #[inline] fn from_fn(cb: F) -> Self where F: FnMut(usize) -> T, @@ -797,6 +843,7 @@ impl FromFn for [T; N] { /// # Panics /// Panics if `N` is 0. #[allow(clippy::arithmetic_side_effects)] +#[inline] pub fn slice_as_chunks(buf: &[T]) -> (&[Array], &[T]) { assert_ne!(N::USIZE, 0, "chunk size must be non-zero"); // Arithmetic safety: we have checked that `N::USIZE` is not zero, thus @@ -819,6 +866,7 @@ pub fn slice_as_chunks(buf: &[T]) -> (&[Array], &[T]) { /// # Panics /// Panics if `N` is 0. #[allow(clippy::arithmetic_side_effects)] +#[inline] pub fn slice_as_chunks_mut(buf: &mut [T]) -> (&mut [Array], &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 diff --git a/hybrid-array/src/sizes.rs b/hybrid-array/src/sizes.rs index af48cb0e..183ca547 100644 --- a/hybrid-array/src/sizes.rs +++ b/hybrid-array/src/sizes.rs @@ -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()) } + } } )+ };