Add ChunksFixed iterator
This commit is contained in:
parent
08ee712448
commit
76c978ae1f
|
@ -10,6 +10,7 @@ mod app;
|
||||||
mod canvas;
|
mod canvas;
|
||||||
mod controls;
|
mod controls;
|
||||||
mod home;
|
mod home;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
#[wasm_bindgen(start)]
|
#[wasm_bindgen(start)]
|
||||||
pub fn run_app() {
|
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