use core::hash::{BuildHasher, Hash};
use core::marker::PhantomData;
use core::pin::Pin;
use core::{fmt, iter};
use std::collections::{HashMap, HashSet};
use std::sync;
use std::vec::Vec;
use itertools::Itertools as _;
use crate::iteration::{peekable_exhaust, FlatZipMap, Pei};
use crate::patterns::impl_newtype_generic;
use crate::Exhaust;
impl<T, S> Exhaust for HashSet<T, S>
where
T: Exhaust + Eq + Hash,
S: Clone + Default + BuildHasher,
{
type Iter = ExhaustHashSet<T, S>;
fn exhaust() -> Self::Iter {
ExhaustHashSet {
iter: itertools::Itertools::powerset(T::exhaust()),
_phantom: PhantomData,
}
}
}
pub struct ExhaustHashSet<T: Exhaust, S> {
iter: itertools::Powerset<<T as Exhaust>::Iter>,
_phantom: PhantomData<fn() -> S>,
}
impl<T, S> Iterator for ExhaustHashSet<T, S>
where
T: Exhaust + Eq + Hash,
S: Default + BuildHasher,
{
type Item = HashSet<T, S>;
fn next(&mut self) -> Option<Self::Item> {
let items: Vec<T> = self.iter.next()?;
let mut set = HashSet::with_capacity_and_hasher(items.len(), S::default());
set.extend(items);
Some(set)
}
}
impl<T: Exhaust, S> Clone for ExhaustHashSet<T, S> {
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
_phantom: PhantomData,
}
}
}
impl<T: Exhaust, S> fmt::Debug for ExhaustHashSet<T, S>
where
T: fmt::Debug,
T::Iter: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("ExhaustHashSet").field(&self.iter).finish()
}
}
impl<K, V, S> Exhaust for HashMap<K, V, S>
where
K: Exhaust + Eq + Hash,
V: Exhaust,
S: Clone + Default + BuildHasher,
{
type Iter = ExhaustHashMap<K, V, S>;
fn exhaust() -> Self::Iter {
let mut keys: Pei<HashSet<K, S>> = peekable_exhaust::<HashSet<K, S>>();
let key_count = keys.peek().map_or(0, HashSet::len);
ExhaustHashMap {
keys,
vals: itertools::repeat_n(V::exhaust(), key_count)
.multi_cartesian_product()
.peekable(),
}
}
}
pub struct ExhaustHashMap<K, V, S>
where
K: Exhaust + Eq + Hash,
V: Exhaust,
S: Clone + Default + BuildHasher,
{
keys: Pei<HashSet<K, S>>,
vals: iter::Peekable<itertools::MultiProduct<<V as Exhaust>::Iter>>,
}
impl<K, V, S> Iterator for ExhaustHashMap<K, V, S>
where
K: Exhaust + Eq + Hash,
V: Exhaust,
S: Clone + Default + BuildHasher,
{
type Item = HashMap<K, V, S>;
fn next(&mut self) -> Option<Self::Item> {
let keys: HashSet<K, S> = self.keys.peek()?.clone();
let vals: Vec<V> = self.vals.next()?;
if self.vals.peek().is_none() {
self.keys.next();
let key_count = self.keys.peek().map_or(0, HashSet::len);
self.vals = itertools::repeat_n(V::exhaust(), key_count)
.multi_cartesian_product()
.peekable();
}
Some(keys.into_iter().zip_eq(vals).collect())
}
}
impl<K, V, S> Clone for ExhaustHashMap<K, V, S>
where
K: Exhaust + Eq + Hash,
V: Exhaust,
S: Clone + Default + BuildHasher,
{
fn clone(&self) -> Self {
Self {
keys: self.keys.clone(),
vals: self.vals.clone(),
}
}
}
impl<K, V, S> fmt::Debug for ExhaustHashMap<K, V, S>
where
K: fmt::Debug + Exhaust + Eq + Hash,
V: fmt::Debug + Exhaust,
K::Iter: fmt::Debug,
V::Iter: fmt::Debug,
S: Clone + Default + BuildHasher,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ExhaustHashMap")
.field("keys", &self.keys)
.field("vals", &self.vals)
.finish()
}
}
impl<T: Exhaust + AsRef<[u8]>> Exhaust for std::io::Cursor<T> {
type Iter = FlatZipMap<<T as Exhaust>::Iter, std::ops::RangeInclusive<u64>, std::io::Cursor<T>>;
fn exhaust() -> Self::Iter {
FlatZipMap::new(
T::exhaust(),
|buf| 0..=(buf.as_ref().len() as u64),
|buf, pos| {
let mut cursor = std::io::Cursor::new(buf);
cursor.set_position(pos);
cursor
},
)
}
}
impl Exhaust for std::io::Empty {
type Iter = iter::Once<std::io::Empty>;
fn exhaust() -> Self::Iter {
iter::once(std::io::empty())
}
}
impl Exhaust for std::io::Sink {
type Iter = iter::Once<std::io::Sink>;
fn exhaust() -> Self::Iter {
iter::once(std::io::sink())
}
}
impl_newtype_generic!(T: [], sync::Arc<T>, sync::Arc::new);
impl_newtype_generic!(T: [], Pin<sync::Arc<T>>, sync::Arc::pin);