Add ChunksFixed iterator
This commit is contained in:
parent
08ee712448
commit
76c978ae1f
|
@ -10,6 +10,7 @@ mod app;
|
|||
mod canvas;
|
||||
mod controls;
|
||||
mod home;
|
||||
mod utils;
|
||||
|
||||
#[wasm_bindgen(start)]
|
||||
pub fn run_app() {
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
/// Utils: general utilities.
|
||||
|
||||
/// An iterator over a slice in a fixed number of non-overlapping
|
||||
/// chunks, starting at the beginning of the slice.
|
||||
///
|
||||
/// When the slice len is not evenly divisible by the number of
|
||||
/// chunks, the length of individual chunks may vary, with each chunk
|
||||
/// being augmented by a single element until the remainder is
|
||||
/// evenly distributed.
|
||||
///
|
||||
/// TODO:
|
||||
/// - implement size_hint, count, etc as appropriate
|
||||
/// - improve test coverage
|
||||
/// - extract to own crate
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ChunksFixed<'a, T: 'a> {
|
||||
v: &'a [T],
|
||||
size: usize,
|
||||
rem: usize,
|
||||
}
|
||||
|
||||
pub fn chunks_fixed<T>(slice: &[T], num_chunks: usize) -> ChunksFixed<T> {
|
||||
ChunksFixed {
|
||||
v: slice,
|
||||
size: slice.len() / num_chunks,
|
||||
rem: slice.len() % num_chunks,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Iterator for ChunksFixed<'a, T> {
|
||||
type Item = &'a [T];
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a [T]> {
|
||||
if self.v.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let s = if self.rem > 0 {
|
||||
self.rem -= 1;
|
||||
self.size + 1
|
||||
} else {
|
||||
self.size
|
||||
};
|
||||
|
||||
let (fst, snd) = self.v.split_at(s);
|
||||
self.v = snd;
|
||||
Some(fst)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_chunks_fixed_10_into_10() {
|
||||
let v = vec![0; 10];
|
||||
let chunks = chunks_fixed(&v, 10).collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(chunks.len(), 10);
|
||||
chunks.iter().for_each(|chunk| assert_eq!(chunk.len(), 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chunks_fixed_100_into_10() {
|
||||
let v = vec![0; 100];
|
||||
let chunks = chunks_fixed(&v, 10).collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(chunks.len(), 10);
|
||||
chunks.iter().for_each(|chunk| assert_eq!(chunk.len(), 10));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chunks_fixed_101_into_10() {
|
||||
let v = vec![0; 101];
|
||||
let chunks = chunks_fixed(&v, 10).collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(chunks.len(), 10);
|
||||
chunks.iter().enumerate().for_each(|(i, chunk)| {
|
||||
if i == 0 {
|
||||
assert_eq!(chunk.len(), 11);
|
||||
} else {
|
||||
assert_eq!(chunk.len(), 10);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chunks_fixed_10399_into_800() {
|
||||
let v = vec![0; 10399];
|
||||
let chunks = chunks_fixed(&v, 800).collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(chunks.len(), 800);
|
||||
chunks.iter().enumerate().for_each(|(i, chunk)| {
|
||||
if i < 799 {
|
||||
assert_eq!(chunk.len(), 13);
|
||||
} else {
|
||||
assert_eq!(chunk.len(), 12);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chunks_fixed_10400_into_800() {
|
||||
let v = vec![0; 10400];
|
||||
let chunks = chunks_fixed(&v, 800).collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(chunks.len(), 800);
|
||||
chunks.iter().for_each(|chunk| {
|
||||
assert_eq!(chunk.len(), 13);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chunks_fixed_10401_into_800() {
|
||||
let v = vec![0; 10401];
|
||||
let chunks = chunks_fixed(&v, 800).collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(chunks.len(), 800);
|
||||
chunks.iter().enumerate().for_each(|(i, chunk)| {
|
||||
if i == 0 {
|
||||
assert_eq!(chunk.len(), 14);
|
||||
} else {
|
||||
assert_eq!(chunk.len(), 13);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue