use crate::IntoNonEmptyIterator;
use crate::NonEmptyIterator;
use core::fmt;
use itertools::Itertools;
use std::fmt::Debug;
pub trait NonEmptyItertools: NonEmptyIterator {
fn cartesian_product<J>(self, other: J) -> Product<Self, J::IntoNEIter>
where
Self: Sized,
Self::Item: Clone,
J: IntoNonEmptyIterator,
<J::IntoNEIter as IntoIterator>::IntoIter: Clone,
{
Product {
inner: Itertools::cartesian_product(self.into_iter(), other.into_nonempty_iter()),
}
}
#[must_use]
fn all_unique(self) -> bool
where
Self: Sized,
Self::Item: Eq + std::hash::Hash,
{
self.into_iter().all_unique()
}
}
impl<T> NonEmptyItertools for T where T: NonEmptyIterator + ?Sized {}
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct Product<I, J>
where
I: NonEmptyIterator,
J: NonEmptyIterator,
{
inner: itertools::Product<I::IntoIter, J::IntoIter>,
}
impl<I, J> NonEmptyIterator for Product<I, J>
where
I: NonEmptyIterator,
J: NonEmptyIterator,
J::Item: Clone,
I::Item: Clone,
J::IntoIter: Clone,
I::IntoIter: Clone,
{
}
impl<I, J> IntoIterator for Product<I, J>
where
I: NonEmptyIterator,
J: NonEmptyIterator,
J::Item: Clone,
I::Item: Clone,
J::IntoIter: Clone,
I::IntoIter: Clone,
{
type Item = (I::Item, J::Item);
type IntoIter = itertools::Product<I::IntoIter, J::IntoIter>;
fn into_iter(self) -> Self::IntoIter {
self.inner
}
}
impl<I, J> Debug for Product<I, J>
where
I: NonEmptyIterator,
J: NonEmptyIterator,
I::Item: Debug,
J::Item: Debug,
I::IntoIter: Debug,
J::IntoIter: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.inner, f)
}
}