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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
use std::convert::TryInto; #[derive(Debug, Clone)] pub struct ChunksExacter<'a, T: 'a, const N: usize> { v: &'a [T], rem: &'a [T], } impl<'a, T, const N: usize> ChunksExacter<'a, T, N> { pub fn new(slice: &'a [T]) -> Self { let rem = slice.len() % N; let fst_len = slice.len() - rem; let (fst, snd) = slice.split_at(fst_len); Self { v: fst, rem: snd } } pub fn remainder(&self) -> &[T] { self.rem } } impl<'a, T, const N: usize> Iterator for ChunksExacter<'a, T, N> { type Item = &'a [T; N]; fn next(&mut self) -> Option<Self::Item> { if self.v.is_empty() { None } else { let (fst, snd) = self.v.split_at(N); self.v = snd; Some(fst.try_into().unwrap()) } } fn size_hint(&self) -> (usize, Option<usize>) { let n = self.v.len() / N; (n, Some(n)) } fn count(self) -> usize { self.size_hint().0 } } impl<'a, T, const N: usize> ExactSizeIterator for ChunksExacter<'a, T, N> {} struct ChunksExactest<'a, T: 'a, const N: usize> { v: &'a [T], } impl<'a, T, const N: usize> ChunksExactest<'a, T, N> { fn new(slice: &'a [T]) -> Self { let rem = slice.len() % N; assert_eq!(rem, 0); Self { v: slice } } } impl<'a, T, const N: usize> Iterator for ChunksExactest<'a, T, N> { type Item = &'a [T; N]; fn next(&mut self) -> Option<Self::Item> { if self.v.is_empty() { None } else { let (fst, snd) = self.v.split_at(N); self.v = snd; Some(fst.try_into().unwrap()) } } fn size_hint(&self) -> (usize, Option<usize>) { let n = self.v.len() / N; (n, Some(n)) } fn count(self) -> usize { self.size_hint().0 } } impl<'a, T, const N: usize> ExactSizeIterator for ChunksExactest<'a, T, N> {} trait ChunksExactExt<'a, T, const N: usize> { fn chunks_exacter(&'a self) -> ChunksExacter<'a, T, N>; fn chunks_exactest(&'a self) -> ChunksExactest<'a, T, N>; } impl<'a, T, const N: usize> ChunksExactExt<'a, T, N> for [T] { fn chunks_exacter(&'a self) -> ChunksExacter<'a, T, N> { ChunksExacter::new(self) } fn chunks_exactest(&'a self) -> ChunksExactest<'a, T, N> { ChunksExactest::new(self) } } #[test] fn test_construct() { let bytes = &[ 1,0,0,1,0,0,0,0, 2,0,0,2,0,0,0,0, ]; let new_things: Vec<_> = bytes .chunks_exacter() .map(|x: &[_; 8]| x[3]) .collect(); assert_eq!(&new_things, &[1, 2]); let new_things: Vec<_> = bytes .chunks_exactest() .map(|x| u32::from_le_bytes(*x)) .collect(); assert_eq!(&new_things, &[0x01000001, 0, 0x02000002, 0]); }