use crate::expression::IMEx;
use std::convert::TryFrom;
use std::io::Result;
pub trait IMExIterator {
fn iterate<T, I>(&mut self, iters: &mut Vec<T>) -> Option<I>
where
T: Iterator<Item = I>;
}
pub struct IMExIter<T, I>
where
T: Iterator<Item = I>,
{
iters: Vec<T>,
imex: IMEx,
}
impl<T, I> IMExIter<T, I>
where
T: Iterator<Item = I>,
{
pub fn new(iters: Vec<T>, imex: &str) -> Result<Self> {
Ok(IMExIter::<T, I> {
iters,
imex: IMEx::try_from(imex)?,
})
}
}
impl<T, I> Iterator for IMExIter<T, I>
where
T: Iterator<Item = I>,
{
type Item = I;
fn next(&mut self) -> Option<Self::Item> {
self.imex.iterate(&mut self.iters)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn non_repeating_imex_might_not_complete() -> Result<()> {
let iters = vec!["00000".chars(), "11111".chars()];
let i = IMExIter::new(iters, "01(10){3}")?;
assert_eq!(i.collect::<String>(), "01101010");
Ok(())
}
#[test]
fn repeating_imex_repeats() -> Result<()> {
let iters = vec!["00000000".chars(), "111111".chars()];
let i = IMExIter::new(iters, "0{3}1(01){5}")?;
assert_eq!(i.collect::<String>(), "00010101010101");
Ok(())
}
#[test]
fn completed_imex_exits_repeating() -> Result<()> {
let iters = vec!["000".chars(), "111".chars(), "22222".chars()];
let i = IMExIter::new(iters, "0*(12)*")?;
assert_eq!(i.collect::<String>(), "00012121222");
Ok(())
}
#[test]
fn out_of_range_imex_skips() -> Result<()> {
let iters = vec!["000".chars(), "111".chars()];
let i = IMExIter::new(iters, "0120")?;
assert_eq!(i.collect::<String>(), "010");
Ok(())
}
#[test]
fn empty_imex_gives_empty_merge() -> Result<()> {
let iters = vec!["000".chars(), "111".chars()];
let i = IMExIter::new(iters, "")?;
assert_eq!(i.collect::<String>(), String::new());
Ok(())
}
#[test]
fn empty_iters_give_empty_merge() -> Result<()> {
let iters = vec!["".chars(), "".chars(), "".chars()];
let i = IMExIter::new(iters, "0120")?;
assert_eq!(i.collect::<String>(), String::new());
Ok(())
}
#[test]
fn empty_iter_list_gives_empty_merge() -> Result<()> {
let iters: Vec<std::str::Chars> = vec![];
let i = IMExIter::new(iters, "0120")?;
assert_eq!(i.collect::<String>(), String::new());
Ok(())
}
}