1#![cfg_attr(not(test), no_std)]
3#![allow(incomplete_features, internal_features)]
4#![feature(
5 const_destruct,
6 adt_const_params,
7 generic_const_exprs,
8 core_intrinsics,
9 iter_intersperse,
10 const_trait_impl,
11 maybe_uninit_array_assume_init,
12 array_windows,
13 iter_map_windows
14)]
15#![warn(
16 clippy::undocumented_unsafe_blocks,
17 clippy::missing_const_for_fn,
18 clippy::missing_safety_doc,
19 clippy::suboptimal_flops,
20 unsafe_op_in_unsafe_fn,
21 clippy::dbg_macro,
22 clippy::use_self,
23 missing_docs
24)]
25use core::{
26 array::from_fn,
27 intrinsics::transmute_unchecked,
28 marker::Destruct,
29 mem::{MaybeUninit as MU, offset_of},
30};
31pub mod pervasive;
32mod slice;
33mod tuple;
34#[doc(inline)]
35pub use slice::Slice;
36pub use tuple::*;
37
38pub mod prelude {
43 #[doc(inline)]
44 pub use super::{
45 Array, ArrayTools, Chunked, CollectArray, Couple, Deconstruct, Flatten, Join, Split, Tuple,
46 Zip, pervasive::prelude::*, range, slice::Slice, slice::r, splat,
47 };
48 #[doc(inline)]
49 pub use core::array::from_fn;
50}
51
52#[repr(C)]
53struct Pair<X, Y>(X, Y);
54impl<X, Y> Pair<X, Y> {
55 const fn tuple() -> bool {
56 (size_of::<(X, Y)>() == size_of::<Self>())
57 & (offset_of!(Self, 0) == offset_of!((X, Y), 0))
58 & (offset_of!(Self, 1) == offset_of!((X, Y), 1))
59 }
60
61 const fn into(self) -> (X, Y) {
62 if Self::tuple() {
63 unsafe { transmute_unchecked::<Self, (X, Y)>(self) }
65 } else {
66 let out = unsafe { (core::ptr::read(&self.0), core::ptr::read(&self.1)) };
68 core::mem::forget(self);
69 out
70 }
71 }
72
73 const unsafe fn splat<T>(x: T) -> (X, Y) {
74 assert!(core::mem::size_of::<T>() == core::mem::size_of::<Pair<X, Y>>());
75 unsafe { transmute_unchecked::<_, Self>(x) }.into()
77 }
78}
79
80pub fn splat<T: Clone, const N: usize>(a: T) -> [T; N] {
82 from_fn(|_| a.clone())
83}
84
85pub const fn range<const N: usize>() -> [usize; N] {
92 let mut out = unsafe { MU::<[MU<usize>; N]>::uninit().assume_init() };
93 let mut i = 0usize;
94 while i < out.len() {
95 out[i] = MU::new(i);
96 i += 1;
97 }
98 unsafe { transmute_unchecked(out) }
99}
100
101pub trait CollectArray<T> {
103 fn carr<const N: usize>(&mut self) -> [T; N];
109}
110
111impl<T, I: Iterator<Item = T>> CollectArray<T> for I {
112 fn carr<const N: usize>(&mut self) -> [T; N] {
113 from_fn(|_| self.next().unwrap())
114 }
115}
116
117pub const trait Deconstruct<T, const N: usize> {
130 fn uncons(self) -> (T, [T; N - 1]);
139 fn unsnoc(self) -> ([T; N - 1], T);
148 fn init(self) -> [T; N - 1];
157 fn tail(self) -> [T; N - 1];
166 fn last(self) -> T
169 where
170 [(); N - 1]:;
171
172 fn head(self) -> T
175 where
176 [(); N - 1]:;
177}
178
179impl<T, const N: usize> const Deconstruct<T, N> for [T; N]
180where
181 T: [const] Destruct,
182{
183 #[doc(alias = "pop_front")]
184 fn uncons(self) -> (T, [T; N - 1]) {
185 unsafe { Pair::splat(self) }
187 }
188
189 #[doc(alias = "pop")]
190 fn unsnoc(self) -> ([T; N - 1], T) {
191 unsafe { Pair::splat(self) }
193 }
194 fn tail(self) -> [T; N - 1]
195 where
196 T: [const] Destruct,
197 {
198 self.uncons().1
199 }
200 #[doc(alias = "trunc")]
201 fn init(self) -> [T; N - 1] {
202 self.unsnoc().0
203 }
204 fn last(self) -> T
205 where
206 [(); N - 1]:,
207 {
208 self.unsnoc().1
209 }
210
211 fn head(self) -> T
212 where
213 [(); N - 1]:,
214 {
215 self.uncons().0
216 }
217}
218
219pub const trait Join<T, const N: usize, const O: usize, U> {
221 fn join(self, with: U) -> [T; N + O];
230}
231
232pub const trait Couple<T, const N: usize, const O: usize> {
234 fn couple(self, with: [T; O]) -> [T; N + O];
241}
242
243impl<T, const N: usize, const O: usize> const Couple<T, N, O> for [T; N] {
244 fn couple(self, with: [T; O]) -> [T; N + O] {
245 unsafe { transmute_unchecked(Pair(self, with)) }
247 }
248}
249
250impl<T, const N: usize> const Join<T, N, 1, T> for [T; N] {
251 fn join(self, with: T) -> [T; N + 1] {
252 self.couple([with])
253 }
254}
255
256impl<T> const Join<T, 1, 1, T> for T {
257 fn join(self, with: T) -> [T; 2] {
258 [self, with]
259 }
260}
261
262impl<T, const O: usize> const Join<T, 1, O, [T; O]> for T {
263 fn join(self, with: [T; O]) -> [T; 1 + O] {
264 [self].couple(with)
265 }
266}
267
268#[allow(private_bounds)]
270pub const trait Chunked<T, const N: usize> {
271 #[allow(private_bounds)]
280 fn chunked<const C: usize>(self) -> [[T; C]; N / C]
281 where
282 [(); N % C + usize::MAX]:;
284}
285
286impl<const N: usize, T> const Chunked<T, N> for [T; N] {
287 #[allow(private_bounds)]
288 fn chunked<const C: usize>(self) -> [[T; C]; N / C]
289 where
290 [(); N % C + usize::MAX]:,
291 {
292 let retval = unsafe { self.as_ptr().cast::<[[T; C]; N / C]>().read() };
294 core::mem::forget(self);
295 retval
296 }
297}
298
299pub const trait Flatten<T, const N: usize, const N2: usize> {
301 fn flatten(self) -> [T; N * N2];
322}
323
324impl<T, const N: usize, const M: usize> const Flatten<T, N, M> for [[T; M]; N] {
325 fn flatten(self) -> [T; N * M] {
326 unsafe { core::intrinsics::transmute_unchecked(self) }
328 }
329}
330
331pub const trait Split<T, const N: usize> {
333 fn split<const AT: usize>(self) -> ([T; AT], [T; N - AT]);
341 fn take<const AT: usize>(self) -> [T; AT]
348 where
349 [(); N - AT]:,
350 T: [const] Destruct;
351 fn drop<const AT: usize>(self) -> [T; N - AT]
353 where
354 T: [const] Destruct;
355}
356
357impl<T, const N: usize> const Split<T, N> for [T; N] {
358 fn split<const AT: usize>(self) -> ([T; AT], [T; N - AT]) {
359 unsafe { Pair::splat(self) }
361 }
362 fn take<const M: usize>(self) -> [T; M]
363 where
364 [(); N - M]:,
366 T: [const] Destruct,
367 {
368 self.split::<M>().0
369 }
370 fn drop<const M: usize>(self) -> [T; N - M]
371 where
372 T: [const] Destruct,
373 {
374 self.split::<M>().1
375 }
376}
377pub const trait Zip<T, const N: usize> {
379 fn zip<U>(self, with: [U; N]) -> [(T, U); N];
381}
382
383impl<T, const N: usize> const Zip<T, N> for [T; N] {
384 fn zip<U>(self, with: [U; N]) -> [(T, U); N] {
385 let mut out = unsafe { MU::<[MU<_>; N]>::uninit().assume_init() };
386 let mut i = 0usize;
387 while i < out.len() {
388 out[i] = MU::new(unsafe { (self.as_ptr().add(i).read(), with.as_ptr().add(i).read()) });
389 i += 1;
390 }
391 core::mem::forget((self, with));
392 unsafe { transmute_unchecked(out) }
393 }
394}
395
396pub trait ArrayTools<T, const N: usize> {
398 fn skip<const BY: usize>(self) -> [T; N - BY];
400 fn step<const STEP: usize>(self) -> [T; 1 + (N - 1) / (STEP)];
412 fn intersperse(self, with: T) -> [T; (N * 2) - 1]
420 where
421 T: Clone;
422 fn each(self, apply: impl FnMut(T));
424 fn enumerate(self) -> [(T, usize); N];
426 fn windowed<const W: usize>(&self) -> [&[T; W]; N - W + 1];
433 fn inspect(self, f: impl FnMut(&T)) -> Self;
435 fn rev(self) -> Self;
437 fn interleave(self, with: [T; N]) -> [T; N * 2];
444 fn cartesian_product<U: Clone, const M: usize>(self, with: &[U; M]) -> [(T, U); N * M]
451 where
452 T: Clone;
453 fn sort(self) -> Self
455 where
456 T: Ord;
457 fn sum(self) -> T
459 where
460 T: core::iter::Sum<T>;
461 fn product(self) -> T
463 where
464 T: core::iter::Product<T>;
465}
466
467impl<T, const N: usize> ArrayTools<T, N> for [T; N] {
468 fn skip<const BY: usize>(self) -> [T; N - BY] {
469 self.into_iter().skip(BY).carr()
470 }
471 fn step<const STEP: usize>(self) -> [T; 1 + (N - 1) / (STEP)] {
472 self.into_iter().step_by(STEP).carr()
473 }
474 fn intersperse(self, with: T) -> [T; (N * 2) - 1]
475 where
476 T: Clone,
477 {
478 self.into_iter().intersperse(with).carr()
479 }
480
481 fn each(self, apply: impl FnMut(T)) {
482 self.into_iter().for_each(apply);
483 }
484
485 fn enumerate(self) -> [(T, usize); N] {
486 let mut n = 0;
487 self.map(|x| {
488 let o = n;
489 n += 1;
490 (x, o)
491 })
492 }
493
494 fn windowed<const W: usize>(&self) -> [&[T; W]; N - W + 1] {
495 self.array_windows().carr()
496 }
497
498 fn inspect(self, f: impl FnMut(&T)) -> Self {
499 self.iter().for_each(f);
500 self
501 }
502
503 fn rev(mut self) -> Self {
504 self.reverse();
505 self
506 }
507
508 fn interleave(self, with: [T; N]) -> [T; N * 2] {
509 let mut which = true;
510 let mut a = self.into_iter();
511 let mut b = with.into_iter();
512 from_fn(|_| {
513 which = !which;
514 match which {
515 false => a.next().unwrap(),
516 true => b.next().unwrap(),
517 }
518 })
519 }
520
521 fn cartesian_product<U: Clone, const M: usize>(self, with: &[U; M]) -> [(T, U); N * M]
522 where
523 T: Clone,
524 {
525 self.map(|a| with.clone().map(move |b| (a.clone(), b)))
526 .flatten()
527 }
528
529 fn sort(mut self) -> Self
530 where
531 T: Ord,
532 {
533 <[T]>::sort_unstable(&mut self);
534 self
535 }
536
537 fn sum(self) -> T
538 where
539 T: core::iter::Sum<T>,
540 {
541 self.into_iter().sum()
542 }
543
544 fn product(self) -> T
545 where
546 T: core::iter::Product<T>,
547 {
548 self.into_iter().product()
549 }
550}