use crate::types::Size;
pub struct StepIterator<'a, T> {
data: &'a [T],
pos: Size,
step: Size,
}
impl<'a, T> Iterator for StepIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.pos >= self.data.len() {
return None;
}
let item = &self.data[self.pos];
self.pos = self.pos.saturating_add(self.step);
Some(item)
}
}
pub fn step_iter<T>(data: &[T], step: Size) -> StepIterator<'_, T> {
assert!(step > 0, "step must be positive");
StepIterator { data, pos: 0, step }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn advances_in_constant_steps() {
let data = [0, 1, 2, 3, 4, 5, 6];
let collected: Vec<i32> = step_iter(&data, 2).copied().collect();
assert_eq!(collected, vec![0, 2, 4, 6]);
}
#[test]
fn step_of_one_yields_every_element() {
let data = [10, 20, 30];
let collected: Vec<i32> = step_iter(&data, 1).copied().collect();
assert_eq!(collected, vec![10, 20, 30]);
}
#[test]
fn step_larger_than_len_yields_first_only() {
let data = [10, 20, 30];
let collected: Vec<i32> = step_iter(&data, 10).copied().collect();
assert_eq!(collected, vec![10]);
}
#[test]
#[should_panic(expected = "step must be positive")]
fn zero_step_panics() {
let _ = step_iter(&[1, 2, 3], 0);
}
}