#![warn(missing_docs)]
#![forbid(unsafe_code)]
use std::collections::{BTreeMap, HashMap};
use std::hash::{BuildHasher, Hash};
pub trait GroupFromIterator<V> {
fn group_from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = V>;
}
impl<K, V, C> GroupFromIterator<(K, V)> for C
where
C: InsertAndExtend<K, V>,
{
#[inline]
fn group_from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (K, V)>,
{
#[derive(Debug)]
enum Never {}
let r: Result<Self, Never> = GroupFromIterator::group_from_iter(iter.into_iter().map(Ok));
r.unwrap()
}
}
impl<K, V, C> GroupFromIterator<Option<(K, V)>> for Option<C>
where
C: InsertAndExtend<K, V>,
{
#[inline]
fn group_from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Option<(K, V)>>,
{
let r: Result<C, ()> =
GroupFromIterator::group_from_iter(iter.into_iter().map(|o| o.ok_or(())));
r.ok()
}
}
impl<K, V, C, E> GroupFromIterator<Result<(K, V), E>> for Result<C, E>
where
C: InsertAndExtend<K, V>,
{
fn group_from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Result<(K, V), E>>,
{
let mut h = C::default();
for r in iter {
let (k, v) = r?;
h.insert_and_extend(k, v);
}
Ok(h)
}
}
pub trait IntoGroup<V> {
fn group<B: GroupFromIterator<V>>(self) -> B;
}
impl<V, I> IntoGroup<V> for I
where
I: Iterator<Item = V>,
{
#[inline]
fn group<B: GroupFromIterator<V>>(self) -> B {
B::group_from_iter(self)
}
}
pub trait InsertAndExtend<K, V>: Default {
fn insert_and_extend(&mut self, key: K, value: V);
}
impl<K, V, E, H> InsertAndExtend<K, V> for HashMap<K, E, H>
where
K: Eq + Hash,
E: Default + Extend<V>,
H: BuildHasher + Default,
{
#[inline]
fn insert_and_extend(&mut self, key: K, value: V) {
self.entry(key).or_default().extend(std::iter::once(value));
}
}
impl<K, V, E> InsertAndExtend<K, V> for BTreeMap<K, E>
where
K: Ord,
E: Default + Extend<V>,
{
#[inline]
fn insert_and_extend(&mut self, key: K, value: V) {
self.entry(key).or_default().extend(std::iter::once(value));
}
}
pub trait SummarizeFromIterator<V> {
fn summarize_from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = V>;
}
impl<K, V, C> SummarizeFromIterator<(K, V)> for C
where
C: InsertAndIncrement<K, V>,
{
#[inline]
fn summarize_from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (K, V)>,
{
#[derive(Debug)]
enum Never {}
let r: Result<Self, Never> =
SummarizeFromIterator::summarize_from_iter(iter.into_iter().map(Ok));
r.unwrap()
}
}
impl<K, V, C> SummarizeFromIterator<Option<(K, V)>> for Option<C>
where
C: InsertAndIncrement<K, V>,
{
#[inline]
fn summarize_from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Option<(K, V)>>,
{
let r: Result<C, ()> =
SummarizeFromIterator::summarize_from_iter(iter.into_iter().map(|o| o.ok_or(())));
r.ok()
}
}
impl<K, V, C, E> SummarizeFromIterator<Result<(K, V), E>> for Result<C, E>
where
C: InsertAndIncrement<K, V>,
{
fn summarize_from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Result<(K, V), E>>,
{
let mut h = C::default();
for r in iter {
let (k, v) = r?;
h.insert_and_increment(k, v);
}
Ok(h)
}
}
pub trait IntoSummary<V> {
fn summarize<B: SummarizeFromIterator<V>>(self) -> B;
}
impl<V, I> IntoSummary<V> for I
where
I: Iterator<Item = V>,
{
#[inline]
fn summarize<B: SummarizeFromIterator<V>>(self) -> B {
B::summarize_from_iter(self)
}
}
pub trait InsertAndIncrement<K, V>: Default {
fn insert_and_increment(&mut self, key: K, value: V);
}
impl<K, V, H> InsertAndIncrement<K, V> for HashMap<K, V, H>
where
K: Eq + Hash,
V: std::ops::AddAssign,
H: BuildHasher + Default,
{
#[inline]
fn insert_and_increment(&mut self, key: K, value: V) {
use std::collections::hash_map::Entry;
match self.entry(key) {
Entry::Occupied(o) => *o.into_mut() += value,
Entry::Vacant(v) => {
v.insert(value);
}
}
}
}
impl<K, V> InsertAndIncrement<K, V> for BTreeMap<K, V>
where
K: Ord,
V: std::ops::AddAssign,
{
#[inline]
fn insert_and_increment(&mut self, key: K, value: V) {
use std::collections::btree_map::Entry;
match self.entry(key) {
Entry::Occupied(o) => *o.into_mut() += value,
Entry::Vacant(v) => {
v.insert(value);
}
}
}
}