ruchei_itertools/
lib.rs

1//! once it is somewhat useful and correct, this might get renamed to `async-itertools`
2//!
3//! or it might not, since we want `route-sink` passthrough, and that's `ruchei`-specific
4//!
5//! this project is largely based off <https://docs.rs/itertools/0.14.0>, which is licensed under
6//! `MIT OR Apache-2.0 `
7
8#![no_std]
9#![cfg_attr(docsrs, feature(doc_cfg))]
10#![cfg_attr(docsrs, doc(cfg_hide(doc)))]
11
12#[cfg(feature = "std")]
13extern crate std;
14
15use core::cmp::Ordering;
16
17use futures_util::{Stream, TryStream};
18#[cfg(feature = "std")]
19use futures_util::{StreamExt, stream::Collect};
20
21use self::{
22    by_fn::ByFn,
23    check::{assert_future, assert_stream},
24    cmp_by::{ByOrd, cmp_by},
25    partial_cmp_by::{ByPartialOrd, partial_cmp_by},
26};
27pub use self::{
28    either_or_both::EitherOrBoth, interleave::interleave, try_zip_lazy::try_zip_lazy,
29    zip_lazy::zip_lazy, zip_longest::zip_longest,
30};
31
32mod advance_by;
33mod all_equal;
34mod by_fn;
35mod check;
36mod cmp_by;
37mod dedup_eager;
38mod either_or_both;
39mod interleave;
40mod macros;
41mod partial_cmp_by;
42mod try_zip_lazy;
43mod zip_lazy;
44mod zip_longest;
45
46pub type AdvanceBy<'a, S> = self::advance_by::AdvanceBy<'a, S>;
47pub type AllEqual<S> = self::all_equal::AllEqual<S>;
48pub type Cmp<L, R> = self::cmp_by::CmpBy<L, R, ByOrd>;
49pub type CmpBy<L, R, F> = self::cmp_by::CmpBy<L, R, ByFn<F>>;
50pub type DedupEager<I> = self::dedup_eager::DedupEager<I>;
51pub type Interleave<I, J> = self::interleave::Interleave<I, J>;
52pub type PartialCmp<L, R> = self::partial_cmp_by::PartialCmpBy<L, R, ByPartialOrd>;
53pub type PartialCmpBy<L, R, F> = self::partial_cmp_by::PartialCmpBy<L, R, ByFn<F>>;
54pub type TryZipLazy<L, R> = self::try_zip_lazy::TryZipLazy<L, R>;
55pub type ZipLazy<L, R> = self::zip_lazy::ZipLazy<L, R>;
56pub type ZipLongest<L, R> = self::zip_longest::ZipLongest<L, R>;
57
58/// `Itertools` for `Stream`s
59///
60/// most combinators also forward [`futures-sink`] and [`route-sink`] methods
61///
62/// [`futures-sink`]: https://docs.rs/futures-sink/0.3
63/// [`route-sink`]: https://docs.rs/route-sink/0.1
64pub trait AsyncItertools: Stream {
65    fn advance_by(&mut self, n: usize) -> AdvanceBy<'_, Self>
66    where
67        Self: Unpin,
68    {
69        assert_future(AdvanceBy {
70            stream: self,
71            remaining: n,
72        })
73    }
74
75    fn all_equal(self) -> AllEqual<Self>
76    where
77        Self: Sized,
78        Self::Item: PartialEq,
79    {
80        assert_future(AllEqual {
81            stream: self,
82            first: None,
83        })
84    }
85
86    #[cfg(feature = "std")]
87    fn collect_vec(self) -> Collect<Self, std::vec::Vec<Self::Item>>
88    where
89        Self: Sized,
90    {
91        self.collect()
92    }
93
94    fn cmp<J>(self, other: J) -> Cmp<Self, J>
95    where
96        Self: Sized,
97        Self::Item: Ord,
98        J: Stream<Item = Self::Item>,
99    {
100        cmp_by(self, other, ByOrd)
101    }
102
103    fn cmp_by<J, F>(self, other: J, cmp: F) -> CmpBy<Self, J, F>
104    where
105        Self: Sized,
106        J: Stream,
107        F: FnMut(&Self::Item, &J::Item) -> Ordering,
108    {
109        cmp_by(self, other, ByFn(cmp))
110    }
111
112    /// deduplicates items, and yields them *as soon as they become available* (that's why `Clone`)
113    fn dedup_eager(self) -> DedupEager<Self>
114    where
115        Self: Sized,
116        Self::Item: PartialEq + Clone,
117    {
118        assert_stream(DedupEager::new(self))
119    }
120
121    fn interleave<J>(self, other: J) -> Interleave<Self, J>
122    where
123        Self: Sized,
124        J: Stream<Item = Self::Item>,
125    {
126        interleave(self, other)
127    }
128
129    fn partial_cmp<J>(self, other: J) -> PartialCmp<Self, J>
130    where
131        Self: Sized,
132        Self::Item: PartialOrd<J::Item>,
133        J: Stream,
134    {
135        partial_cmp_by(self, other, ByPartialOrd)
136    }
137
138    fn partial_cmp_by<J, F>(self, other: J, cmp: F) -> PartialCmpBy<Self, J, F>
139    where
140        Self: Sized,
141        J: Stream,
142        F: FnMut(&Self::Item, &J::Item) -> Option<Ordering>,
143    {
144        partial_cmp_by(self, other, ByFn(cmp))
145    }
146
147    fn try_zip_lazy<J>(self, other: J) -> TryZipLazy<Self, J>
148    where
149        Self: Sized + TryStream,
150        J: TryStream<Error = Self::Error>,
151    {
152        try_zip_lazy(self, other)
153    }
154
155    fn zip_lazy<J>(self, other: J) -> ZipLazy<Self, J>
156    where
157        Self: Sized,
158        J: Stream,
159    {
160        zip_lazy(self, other)
161    }
162
163    fn zip_longest<J>(self, other: J) -> ZipLongest<Self, J>
164    where
165        Self: Sized,
166        J: Stream,
167    {
168        zip_longest(self, other)
169    }
170}
171
172impl<T: ?Sized + Stream> AsyncItertools for T {}