konst/slice/
slice_as_chunks.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::slice;

/// Const equivalent of
/// [`<[T]>::as_chunks`](https://doc.rust-lang.org/std/primitive.slice.html#method.as_chunks)
///
/// The equivalent std function is unstable as of Rust 1.83.0.
///
/// # Panics
///
/// Panics if `N == 0`.
///
/// # Example
///
/// ```rust
/// use konst::slice;
///
/// let (arrs, rem) = slice::as_chunks::<_, 3>(&[2u32, 3, 5, 8, 13, 21, 34, 55]);
///
/// assert_eq!(arrs, &[[2, 3, 5], [8, 13, 21]][..]);
/// assert_eq!(rem, &[34, 55][..])
///
/// ```
#[track_caller]
pub const fn as_chunks<'a, T, const N: usize>(this: &[T]) -> (&[[T; N]], &[T]) {
    assert!(N != 0, "chunk size must be non-zero");

    let arrs_len = this.len() / N;
    let (arrs_in, rem) = slice::split_at(this, arrs_len * N);

    // SAFETY: `arrs_in` is a `&[T]` that is `arrs_len * N` long,
    // its layout is compatible with the `&[[T; N]]` that this produces.
    let arrs: &[[T; N]] =
        unsafe { core::slice::from_raw_parts(arrs_in.as_ptr() as *const [T; N], arrs_len) };

    (arrs, rem)
}

/// Const equivalent of
/// [`<[T]>::as_rchunks`](https://doc.rust-lang.org/std/primitive.slice.html#method.as_rchunks)
///
/// The equivalent std function is unstable as of Rust 1.83.0.
///
/// # Panics
///
/// Panics if `N == 0`.
///
/// # Example
///
/// ```rust
/// use konst::slice;
///
/// let (rem, arrs) = slice::as_rchunks::<_, 2>(&[2u32, 3, 5, 8, 13, 21, 34]);
///
/// assert_eq!(rem, &[2][..]);
/// assert_eq!(arrs, &[[3, 5], [8, 13], [21, 34]][..]);
/// ```
#[track_caller]
pub const fn as_rchunks<'a, T, const N: usize>(this: &[T]) -> (&[T], &[[T; N]]) {
    assert!(N != 0, "chunk size must be non-zero");

    let arrs_len = this.len() / N;
    let rem_len = this.len() % N;
    let (rem, arrs_in) = slice::split_at(this, rem_len);

    // SAFETY: `arrs_in` is a `&[T]` that is `arrs_len * N` long,
    // its layout is compatible with the `&[[T; N]]` that this produces.
    let arrs: &[[T; N]] =
        unsafe { core::slice::from_raw_parts(arrs_in.as_ptr() as *const [T; N], arrs_len) };

    (rem, arrs)
}