const generic expr based fixed length array manipulation crate
constify zip
bendn 5 months ago
parent 9903f65 · commit 761337c
-rw-r--r--src/lib.rs44
-rw-r--r--src/pervasive.rs2
-rw-r--r--src/slice.rs2
3 files changed, 35 insertions, 13 deletions
diff --git a/src/lib.rs b/src/lib.rs
index b7b781f..7536296 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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)
}