//! 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; fn fold_default(self, f: F) -> impl Future + Send where F: Fn(T, Item) -> Fut + Send, Fut: Future + Send, T: Default + Send; } 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 }) } #[inline] fn fold_default(self, f: F) -> impl Future + Send where F: Fn(T, Item) -> Fut + Send, Fut: Future + Send, T: Default + Send, { self.fold(T::default(), f) } }