konst/slice/slice_as_chunks.rs
1use crate::slice;
2
3/// Const equivalent of
4/// [`<[T]>::as_chunks`](https://doc.rust-lang.org/std/primitive.slice.html#method.as_chunks)
5///
6/// The equivalent std function is unstable as of Rust 1.83.0.
7///
8/// # Panics
9///
10/// Panics if `N == 0`.
11///
12/// # Example
13///
14/// ```rust
15/// use konst::slice;
16///
17/// let (arrs, rem) = slice::as_chunks::<_, 3>(&[2u32, 3, 5, 8, 13, 21, 34, 55]);
18///
19/// assert_eq!(arrs, &[[2, 3, 5], [8, 13, 21]][..]);
20/// assert_eq!(rem, &[34, 55][..])
21///
22/// ```
23#[track_caller]
24pub const fn as_chunks<'a, T, const N: usize>(this: &[T]) -> (&[[T; N]], &[T]) {
25 assert!(N != 0, "chunk size must be non-zero");
26
27 let arrs_len = this.len() / N;
28 let (arrs_in, rem) = slice::split_at(this, arrs_len * N);
29
30 // SAFETY: `arrs_in` is a `&[T]` that is `arrs_len * N` long,
31 // its layout is compatible with the `&[[T; N]]` that this produces.
32 let arrs: &[[T; N]] =
33 unsafe { core::slice::from_raw_parts(arrs_in.as_ptr() as *const [T; N], arrs_len) };
34
35 (arrs, rem)
36}
37
38/// Const equivalent of
39/// [`<[T]>::as_rchunks`](https://doc.rust-lang.org/std/primitive.slice.html#method.as_rchunks)
40///
41/// The equivalent std function is unstable as of Rust 1.83.0.
42///
43/// # Panics
44///
45/// Panics if `N == 0`.
46///
47/// # Example
48///
49/// ```rust
50/// use konst::slice;
51///
52/// let (rem, arrs) = slice::as_rchunks::<_, 2>(&[2u32, 3, 5, 8, 13, 21, 34]);
53///
54/// assert_eq!(rem, &[2][..]);
55/// assert_eq!(arrs, &[[3, 5], [8, 13], [21, 34]][..]);
56/// ```
57#[track_caller]
58pub const fn as_rchunks<'a, T, const N: usize>(this: &[T]) -> (&[T], &[[T; N]]) {
59 assert!(N != 0, "chunk size must be non-zero");
60
61 let arrs_len = this.len() / N;
62 let rem_len = this.len() % N;
63 let (rem, arrs_in) = slice::split_at(this, rem_len);
64
65 // SAFETY: `arrs_in` is a `&[T]` that is `arrs_len * N` long,
66 // its layout is compatible with the `&[[T; N]]` that this produces.
67 let arrs: &[[T; N]] =
68 unsafe { core::slice::from_raw_parts(arrs_in.as_ptr() as *const [T; N], arrs_len) };
69
70 (rem, arrs)
71}