//! StreamTools for futures::Stream use std::{collections::HashMap, hash::Hash}; use futures::{Future, Stream, StreamExt}; use super::ReadyExt; use crate::expected; /// StreamTools /// /// This interface is not necessarily complete; feel free to add as-needed. pub trait Tools where Self: Stream + Send + Sized, ::Item: Send, { fn counts(self) -> impl Future> + Send where ::Item: Eq + Hash; fn counts_by(self, f: F) -> impl Future> + Send where F: Fn(Item) -> K + Send, K: Eq + Hash + Send; fn counts_by_with_cap(self, f: F) -> impl Future> + Send where F: Fn(Item) -> K + Send, K: Eq + Hash + Send; fn counts_with_cap(self) -> impl Future> + Send where ::Item: Eq + Hash; } impl Tools for S where S: Stream + Send + Sized, ::Item: Send, { #[inline] fn counts(self) -> impl Future> + Send where ::Item: Eq + Hash, { self.counts_with_cap::<0>() } #[inline] fn counts_by(self, f: F) -> impl Future> + Send where F: Fn(Item) -> K + Send, K: Eq + Hash + Send, { self.counts_by_with_cap::<0, K, F>(f) } #[inline] fn counts_by_with_cap(self, f: F) -> impl Future> + Send where F: Fn(Item) -> K + Send, K: Eq + Hash + Send, { self.map(f).counts_with_cap::() } #[inline] fn counts_with_cap(self) -> impl Future> + Send where ::Item: Eq + Hash, { self.ready_fold(HashMap::with_capacity(CAP), |mut counts, item| { let entry = counts.entry(item).or_default(); let value = *entry; *entry = expected!(value + 1); counts }) } }