const generic expr based fixed length array manipulation crate
constify zip
| -rw-r--r-- | src/lib.rs | 44 | ||||
| -rw-r--r-- | src/pervasive.rs | 2 | ||||
| -rw-r--r-- | src/slice.rs | 2 |
3 files changed, 35 insertions, 13 deletions
@@ -2,6 +2,7 @@ #![cfg_attr(not(test), no_std)] #![allow(incomplete_features, internal_features)] #![feature( + const_destruct, adt_const_params, generic_const_exprs, core_intrinsics, @@ -24,6 +25,7 @@ use core::{ array::from_fn, intrinsics::transmute_unchecked, + marker::Destruct, mem::{offset_of, MaybeUninit as MU}, }; pub mod pervasive; @@ -41,7 +43,7 @@ pub mod prelude { #[doc(inline)] pub use super::{ pervasive::prelude::*, range, slice::r, slice::Slice, splat, Array, ArrayTools, Chunked, - CollectArray, Couple, Deconstruct, Flatten, Join, Split, Tuple, + CollectArray, Couple, Deconstruct, Flatten, Join, Split, Tuple, Zip, }; #[doc(inline)] pub use core::array::from_fn; @@ -344,12 +346,15 @@ pub trait Split<T, const N: usize> { /// ``` fn take<const AT: usize>(self) -> [T; AT] where - [(); N - AT]:; + [(); N - AT]:, + T: [const] Destruct; /// Discard `AT` elements, returning the rest. - fn drop<const AT: usize>(self) -> [T; N - AT]; + fn drop<const AT: usize>(self) -> [T; N - AT] + where + T: [const] Destruct; } -impl<T, const N: usize> Split<T, N> for [T; N] { +impl<T, const N: usize> const Split<T, N> for [T; N] { fn split<const AT: usize>(self) -> ([T; AT], [T; N - AT]) { // SAFETY: N - AT overflows when AT > N so the size of the returned "array" is the same. unsafe { Pair::splat(self) } @@ -358,13 +363,36 @@ impl<T, const N: usize> Split<T, N> for [T; N] { where // M <= N [(); N - M]:, + T: [const] Destruct, { self.split::<M>().0 } - fn drop<const M: usize>(self) -> [T; N - M] { + fn drop<const M: usize>(self) -> [T; N - M] + where + T: [const] Destruct, + { self.split::<M>().1 } } +#[const_trait] +/// Zip arrays together. +pub trait Zip<T, const N: usize> { + /// Zip arrays together. + fn zip<U>(self, with: [U; N]) -> [(T, U); N]; +} + +impl<T, const N: usize> const Zip<T, N> for [T; N] { + fn zip<U>(self, with: [U; N]) -> [(T, U); N] { + let mut out = unsafe { MU::<[MU<_>; N]>::uninit().assume_init() }; + let mut i = 0usize; + while i < out.len() { + out[i] = MU::new(unsafe { (self.as_ptr().add(i).read(), with.as_ptr().add(i).read()) }); + i += 1; + } + core::mem::forget((self, with)); + unsafe { transmute_unchecked(out) } + } +} /// Array tools. pub trait ArrayTools<T, const N: usize> { @@ -382,8 +410,6 @@ pub trait ArrayTools<T, const N: usize> { /// assert_eq!(range::<50>().step::<3>(), [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48]); /// ``` fn step<const STEP: usize>(self) -> [T; 1 + (N - 1) / (STEP)]; - /// Zip arrays together. - fn zip<U>(self, with: [U; N]) -> [(T, U); N]; /// Intersperse a element in between items. /// ``` /// # #![feature(generic_const_exprs)] @@ -446,10 +472,6 @@ impl<T, const N: usize> ArrayTools<T, N> for [T; N] { fn step<const STEP: usize>(self) -> [T; 1 + (N - 1) / (STEP)] { self.into_iter().step_by(STEP).carr() } - fn zip<U>(self, with: [U; N]) -> [(T, U); N] { - self.into_iter().zip(with).carr() - } - fn intersperse(self, with: T) -> [T; (N * 2) - 1] where T: Clone, diff --git a/src/pervasive.rs b/src/pervasive.rs index 26aa907..7dc784c 100644 --- a/src/pervasive.rs +++ b/src/pervasive.rs @@ -69,7 +69,7 @@ mod array_and_array { impl<T: core::ops::$op<Output = T> + Copy, const N: usize> $n<T, N> for [T; N] { fn $name(self, rhs: [T; N]) -> Self { - use crate::ArrayTools; + use crate::Zip; self.zip(rhs).map(|(a, b)| core::ops::$op::$f(a, b)) } } diff --git a/src/slice.rs b/src/slice.rs index 3279999..d44acf5 100644 --- a/src/slice.rs +++ b/src/slice.rs @@ -61,7 +61,7 @@ impl const Ranged for RangeToInclusive<usize> { /// /// Takes a type in the form {[`Range`], [`RangeInclusive`], [`RangeTo`], [`RangeToInclusive`]}. #[allow(private_bounds)] -pub const fn r<T: ~const Ranged>(x: T) -> Range { +pub const fn r<T: [const] Ranged>(x: T) -> Range { Ranged::range(x) } |