#[cfg(test)]
mod bigram_test;
#[cfg(test)]
mod trigram_test;
use crate::{state::State, Iterable};
use std::mem::MaybeUninit;
pub struct Iter<T, I, const N: usize>
where
T: Copy + Iterable,
I: Iterator<Item = T>,
{
it: I,
state: State<T>,
}
impl<T, I, const N: usize> Iterator for Iter<T, I, N>
where
T: Iterable + Copy,
I: Iterator<Item = T>,
{
type Item = [T; N];
fn next(&mut self) -> Option<Self::Item> {
if N < 2 {
panic!("ngram must have N of 2 or more")
}
let mut out: [MaybeUninit<T>; N] = MaybeUninit::uninit_array();
match self.state {
State::Start => {
if let Some(item) = self.it.next() {
self.state = item.into();
out[0] = MaybeUninit::new(T::bumper_item());
out[1] = MaybeUninit::new(item);
} else {
self.state = State::End;
return None;
}
for i in 2..N {
if let Some(item) = self.it.next() {
self.state = item.into();
out[i] = MaybeUninit::new(item);
} else {
self.state = State::End;
for j in i..N {
out[j] = MaybeUninit::new(T::bumper_item());
}
}
}
}
State::Middle(item) => {
out[0] = MaybeUninit::new(item);
for i in 1..N {
if let Some(item) = self.it.next() {
self.state = State::Middle(item);
out[i] = MaybeUninit::new(item);
} else {
self.state = State::End;
for j in i..N {
out[j] = MaybeUninit::new(T::bumper_item());
}
}
}
}
State::End => return None,
}
Some(unsafe { MaybeUninit::array_assume_init(out) })
}
}
impl<T, I, const N: usize> From<I> for Iter<T, I, N>
where
T: Copy + Iterable,
I: Iterator<Item = T>,
{
fn from(it: I) -> Self {
Self {
it,
state: State::Start,
}
}
}