use core::fmt;
use core::fmt::Debug;
use core::iter::FusedIterator;
use crate::adaptors::generic_combinations::GenericCombinations;
pub trait IterCombinationsWithReps: Iterator {
#[inline]
fn combinations_with_reps(self, k: usize) -> CombinationsWithReps<Self>
where
Self: Sized,
Self::Item: Clone,
{
CombinationsWithReps::new(self, k)
}
}
impl<I: ?Sized> IterCombinationsWithReps for I where I: Iterator {}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct CombinationsWithReps<I>(GenericCombinations<I, Vec<usize>>)
where
I: Iterator;
impl<I> CombinationsWithReps<I>
where
I: Iterator,
{
#[track_caller]
pub(crate) fn new(iter: I, k: usize) -> Self {
assert!(k != 0, "combination size must be non-zero");
Self(GenericCombinations::new(iter, vec![0; k]))
}
}
impl<I> Debug for CombinationsWithReps<I>
where
I: Iterator + Debug,
I::Item: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt_with(f, "CombinationsWithReps")
}
}
impl<I> Clone for CombinationsWithReps<I>
where
I: Iterator + Clone,
I::Item: Clone,
{
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<I> Iterator for CombinationsWithReps<I>
where
I: Iterator,
I::Item: Clone,
{
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
self.0.fill_next_with_reps().map(Vec::from_iter)
}
}
impl<I> FusedIterator for CombinationsWithReps<I>
where
I: Iterator,
I::Item: Clone,
{
}