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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// devela::sys::mem::view::slice::namespace::chunk
use crate::{Slice, is, lets};
/// # `*chunk*` API methods for subslicing.
#[rustfmt::skip]
impl<T> Slice<T> {
/// Returns the number of complete `N`-sized chunks in `slice` and the trailing remainder.
///
/// This is the fixed-step primitive for const-friendly traversal.
///
/// # Example
/// ```
/// # use devela::Slice;
/// let bytes = b"abcdefg";
/// let (count, rem) = Slice::chunks_exact::<3>(bytes);
/// assert_eq!(count, 2); // "abc", "def"
/// assert_eq!(rem, b"g");
/// ```
pub const fn chunks_exact<const N: usize>(slice: &[T]) -> (usize, &[T]) {
lets![full=slice.len()/N, rem_start=full*N];
(full, Slice::range_from(slice, rem_start))
}
/// Mutable counterpart to [`chunks_exact`][Self::chunks_exact].
///
/// Returns the number of complete `N`-sized chunks and a mutable remainder slice.
/// The caller performs any iteration or stepping logic.
pub const fn chunks_exact_mut<const N: usize>(slice: &mut [T]) -> (usize, &mut [T]) {
lets![full=slice.len()/N, rem_start=full*N];
(full, Slice::range_from_mut(slice, rem_start))
}
/// Returns the `idx`-th complete chunk of size `N`, or `None` if incomplete.
///
/// This offers direct, index-based access to fixed-width records.
/// Bounds are checked; no iteration policy is imposed.
///
/// # Example
/// ```
/// # use devela::Slice;
/// let b = b"abcdefgh";
/// assert_eq!(Slice::chunk::<3>(b, 0), Some(&b"abc"[..]));
/// assert_eq!(Slice::chunk::<3>(b, 1), Some(&b"def"[..]));
/// assert_eq!(Slice::chunk::<3>(b, 2), None); // only "gh" remains, not enough for a full chunk
/// ```
pub const fn chunk<const N: usize>(slice: &[T], idx: usize) -> Option<&[T]> {
lets![start=idx*N, end=start+N];
is![end <= slice.len(), Some(Slice::range(slice, start, end)), None]
}
/// Mutable counterpart to [`chunk`][Self::chunk].
///
/// Returns the `idx`-th complete chunk of size `N` as a mutable subslice,
/// or `None` if the chunk is incomplete.
///
/// # Example
/// ```
/// # use devela::Slice;
/// let mut b = *b"abcdef";
/// if let Some(ch) = Slice::chunk_mut::<3>(&mut b, 1) {
/// ch[0] = b'X';
/// }
/// assert_eq!(&b, b"abcXef");
/// ```
pub const fn chunk_mut<const N: usize>(slice: &mut [T], idx: usize) -> Option<&mut [T]> {
lets![start=idx*N, end=start+N];
is![end <= slice.len(), Some(Slice::range_mut(slice, start, end)), None]
}
}
#[test]
#[cfg(test)]
fn test_chunks() {
let mut buf = [10, 11, 12, 13, 14, 15, 16];
// chunks_exact
let (count, rem) = Slice::chunks_exact::<3>(&buf);
assert_eq!(count, 2); // [10,11,12] , [13,14,15]
assert_eq!(rem, &[16]);
// chunks_exact_mut
let (count_mut, rem_mut) = Slice::chunks_exact_mut::<3>(&mut buf);
assert_eq!(count_mut, 2);
assert_eq!(rem_mut, &mut [16]);
// chunk
let c0 = Slice::chunk::<3>(&buf, 0).unwrap();
let c1 = Slice::chunk::<3>(&buf, 1).unwrap();
assert_eq!(c0, &[10, 11, 12]);
assert_eq!(c1, &[13, 14, 15]);
assert!(Slice::chunk::<3>(&buf, 2).is_none());
// chunk_mut
is![let Some(c0m) = Slice::chunk_mut::<3>(&mut buf, 0), c0m[0] = 99];
assert_eq!(buf[0], 99);
}