1use std::future::Future;
4use std::hash::Hash;
5use std::time::Duration;
6
7use futures::Stream;
8use futures::StreamExt as _;
9use rskit_errors::AppResult;
10
11use crate::operators::{concurrent, rate, transform, windowing};
12
13#[allow(async_fn_in_trait)]
17pub trait RskitStreamExt: Stream + Sized + Send + 'static
18where
19 Self::Item: Send + 'static,
20{
21 fn rmap<O, F, Fut>(self, f: F) -> impl Stream<Item = AppResult<O>> + Send + 'static
23 where
24 O: Send + 'static,
25 F: FnMut(Self::Item) -> Fut + Send + 'static,
26 Fut: Future<Output = AppResult<O>> + Send + 'static,
27 {
28 self.then(f)
29 }
30
31 fn rflatmap<O, F, Fut, St>(self, f: F) -> impl Stream<Item = AppResult<O>> + Send + 'static
33 where
34 O: Send + 'static,
35 F: FnMut(Self::Item) -> Fut + Send + 'static,
36 Fut: Future<Output = AppResult<St>> + Send + 'static,
37 St: Stream<Item = AppResult<O>> + Send + Unpin + 'static,
38 {
39 self.then(f).flat_map(|result| match result {
40 Ok(s) => s.left_stream(),
41 Err(e) => futures::stream::once(futures::future::ready(Err(e))).right_stream(),
42 })
43 }
44
45 fn rfilter<F>(self, mut f: F) -> impl Stream<Item = Self::Item> + Send + 'static
47 where
48 F: FnMut(&Self::Item) -> bool + Send + 'static,
49 {
50 self.filter(move |item| {
51 let keep = f(item);
52 std::future::ready(keep)
53 })
54 }
55
56 fn rdistinct(self) -> impl Stream<Item = Self::Item> + Send + 'static
58 where
59 Self::Item: Clone + Eq + Hash,
60 {
61 transform::distinct(self)
62 }
63
64 fn rtap<F, Fut>(self, mut f: F) -> impl Stream<Item = Self::Item> + Send + 'static
66 where
67 F: FnMut(&Self::Item) -> Fut + Send + 'static,
68 Fut: Future<Output = ()> + Send + 'static,
69 {
70 self.then(move |item| {
71 let fut = f(&item);
72 async move {
73 fut.await;
74 item
75 }
76 })
77 }
78
79 fn rtake(self, n: usize) -> impl Stream<Item = Self::Item> + Send + 'static {
81 self.take(n)
82 }
83
84 fn rskip(self, n: usize) -> impl Stream<Item = Self::Item> + Send + 'static {
86 self.skip(n)
87 }
88
89 fn rpartition<F>(
91 self,
92 predicate: F,
93 ) -> (
94 impl Stream<Item = Self::Item> + Send + 'static,
95 impl Stream<Item = Self::Item> + Send + 'static,
96 )
97 where
98 F: FnMut(&Self::Item) -> bool + Send + 'static,
99 {
100 transform::partition(self, predicate)
101 }
102
103 async fn rreduce<Acc, F>(self, init: Acc, mut f: F) -> Acc
105 where
106 Acc: Send + 'static,
107 F: FnMut(Acc, Self::Item) -> Acc + Send + 'static,
108 {
109 let mut acc = init;
110 let this = self;
111 tokio::pin!(this);
112 while let Some(item) = this.next().await {
113 acc = f(acc, item);
114 }
115 acc
116 }
117
118 fn rparallel<O, F, Fut>(
120 self,
121 concurrency: usize,
122 f: F,
123 ) -> impl Stream<Item = AppResult<O>> + Send + 'static
124 where
125 O: Send + 'static,
126 F: Fn(Self::Item) -> Fut + Clone + Send + Sync + 'static,
127 Fut: Future<Output = AppResult<O>> + Send + 'static,
128 {
129 concurrent::parallel(self, concurrency, f)
130 }
131
132 fn rfan_out<O, F, Fut>(
134 self,
135 max_branches: usize,
136 fns: Vec<F>,
137 ) -> impl Stream<Item = AppResult<Vec<O>>> + Send + 'static
138 where
139 O: Send + 'static,
140 Self::Item: Clone,
141 F: Fn(Self::Item) -> Fut + Clone + Send + Sync + 'static,
142 Fut: Future<Output = AppResult<O>> + Send + 'static,
143 {
144 concurrent::fan_out(self, max_branches, fns)
145 }
146
147 fn rtumbling_window(
149 self,
150 duration: Duration,
151 max_items: usize,
152 ) -> impl Stream<Item = Vec<Self::Item>> + Send + 'static {
153 windowing::tumbling_window(self, duration, max_items)
154 }
155
156 fn rsliding_window(
158 self,
159 size: usize,
160 step: usize,
161 ) -> impl Stream<Item = Vec<Self::Item>> + Send + 'static
162 where
163 Self::Item: Clone,
164 {
165 windowing::sliding_window(self, size, step)
166 }
167
168 fn rbatch(
170 self,
171 size: usize,
172 timeout: Duration,
173 ) -> impl Stream<Item = Vec<Self::Item>> + Send + 'static {
174 windowing::batch(self, size, timeout)
175 }
176
177 fn rdebounce(self, delay: Duration) -> impl Stream<Item = Self::Item> + Send + 'static {
179 rate::debounce(self, delay)
180 }
181
182 fn rdebounce_batch(
186 self,
187 quiet: Duration,
188 max_items: usize,
189 ) -> impl Stream<Item = Vec<Self::Item>> + Send + 'static {
190 rate::debounce_batch(self, quiet, max_items)
191 }
192
193 fn rthrottle(self, interval: Duration) -> impl Stream<Item = Self::Item> + Send + 'static {
195 rate::throttle(self, interval)
196 }
197
198 fn rmerge(
200 self,
201 other: impl Stream<Item = Self::Item> + Send + 'static,
202 ) -> impl Stream<Item = Self::Item> + Send + 'static {
203 futures::stream::select(self, other)
204 }
205}
206
207impl<S> RskitStreamExt for S
208where
209 S: Stream + Send + 'static,
210 S::Item: Send + 'static,
211{
212}