Skip to main content

chunks_exacter/
lib.rs

1use std::convert::TryInto;
2
3#[derive(Debug, Clone)]
4pub struct ChunksExacter<'a, T: 'a, const N: usize> {
5    v: &'a [T],
6    rem: &'a [T],
7}
8
9impl<'a, T, const N: usize> ChunksExacter<'a, T, N> {
10    pub fn new(slice: &'a [T]) -> Self {
11        let rem = slice.len() % N;
12        let fst_len = slice.len() - rem;
13
14        let (fst, snd) = slice.split_at(fst_len);
15        Self { v: fst, rem: snd }
16    }
17
18    pub fn remainder(&self) -> &[T] {
19        self.rem
20    }
21}
22
23impl<'a, T, const N: usize> Iterator for ChunksExacter<'a, T, N> {
24    type Item = &'a [T; N];
25
26    fn next(&mut self) -> Option<Self::Item> {
27        if self.v.is_empty() {
28            None
29        } else {
30            let (fst, snd) = self.v.split_at(N);
31            self.v = snd;
32            Some(fst.try_into().unwrap())
33        }
34    }
35
36    fn size_hint(&self) -> (usize, Option<usize>) {
37        let n = self.v.len() / N;
38        (n, Some(n))
39    }
40
41    fn count(self) -> usize {
42        self.size_hint().0
43    }
44}
45
46impl<'a, T, const N: usize> ExactSizeIterator for ChunksExacter<'a, T, N> {}
47
48struct ChunksExactest<'a, T: 'a, const N: usize> {
49    v: &'a [T],
50}
51
52impl<'a, T, const N: usize> ChunksExactest<'a, T, N> {
53    fn new(slice: &'a [T]) -> Self {
54        let rem = slice.len() % N;
55        assert_eq!(rem, 0);
56
57        Self { v: slice }
58    }
59}
60
61impl<'a, T, const N: usize> Iterator for ChunksExactest<'a, T, N> {
62    type Item = &'a [T; N];
63
64    fn next(&mut self) -> Option<Self::Item> {
65        if self.v.is_empty() {
66            None
67        } else {
68            let (fst, snd) = self.v.split_at(N);
69            self.v = snd;
70            Some(fst.try_into().unwrap())
71        }
72    }
73
74    fn size_hint(&self) -> (usize, Option<usize>) {
75        let n = self.v.len() / N;
76        (n, Some(n))
77    }
78
79    fn count(self) -> usize {
80        self.size_hint().0
81    }
82}
83
84impl<'a, T, const N: usize> ExactSizeIterator for ChunksExactest<'a, T, N> {}
85
86trait ChunksExactExt<'a, T, const N: usize> {
87    fn chunks_exacter(&'a self) -> ChunksExacter<'a, T, N>;
88    fn chunks_exactest(&'a self) -> ChunksExactest<'a, T, N>;
89}
90
91impl<'a, T, const N: usize> ChunksExactExt<'a, T, N> for [T] {
92    fn chunks_exacter(&'a self) -> ChunksExacter<'a, T, N> {
93        ChunksExacter::new(self)
94    }
95
96    fn chunks_exactest(&'a self) -> ChunksExactest<'a, T, N> {
97        ChunksExactest::new(self)
98    }
99}
100
101#[test]
102fn test_construct() {
103    let bytes = &[
104        1,0,0,1,0,0,0,0,
105        2,0,0,2,0,0,0,0,
106    ];
107
108    let new_things: Vec<_> = bytes
109        .chunks_exacter()
110        .map(|x: &[_; 8]| x[3])
111        .collect();
112
113    assert_eq!(&new_things, &[1, 2]);
114
115    let new_things: Vec<_> = bytes
116        .chunks_exactest()
117        .map(|x| u32::from_le_bytes(*x))
118        .collect();
119
120    assert_eq!(&new_things, &[0x01000001, 0, 0x02000002, 0]);
121}