1use std::fmt::Display;
29
30use zrx_scheduler::step::error::IntoResult;
31use zrx_scheduler::step::{Result, Scope};
32use zrx_scheduler::Key;
33
34use crate::stream::function::arguments::{
35 ForId, ForIdSplat, ForIdValue, ForKey, ForKeySplat, ForKeyValue, ForScope,
36 ForScopeSplat, ForScopeValue, ForSplat, ForValue,
37};
38use crate::stream::function::catch;
39
40pub trait FlatMapFn<A, J, I, T, U>: Send + 'static {
46 type Iter: IntoIterator<Item = (Key<I>, U)>;
48
49 fn execute(&self, scope: &mut Scope<I>, value: T) -> Result<Self::Iter>;
55}
56
57impl<F, R, J, I, T, U> FlatMapFn<ForScope, J, I, T, U> for F
62where
63 F: Fn(&mut Scope<I>) -> R + Send + 'static,
64 R: IntoResult<J>,
65 J: IntoIterator<Item = (Key<I>, U)>,
66 I: Display,
67{
68 type Iter = J;
69
70 #[cfg_attr(
71 feature = "tracing",
72 tracing::instrument(
73 level = "debug", skip_all, fields(key = %scope.key())
74 )
75 )]
76 #[inline]
77 fn execute(&self, scope: &mut Scope<I>, _: T) -> Result<J> {
78 catch(|| self(scope).into_result())
79 }
80}
81
82impl<F, R, J, I, T, U> FlatMapFn<ForScopeValue, J, I, T, U> for F
83where
84 F: Fn(&mut Scope<I>, T) -> R + Send + 'static,
85 R: IntoResult<J>,
86 J: IntoIterator<Item = (Key<I>, U)>,
87 I: Display,
88{
89 type Iter = J;
90
91 #[cfg_attr(
92 feature = "tracing",
93 tracing::instrument(
94 level = "debug", skip_all, fields(key = %scope.key())
95 )
96 )]
97 #[inline]
98 fn execute(&self, scope: &mut Scope<I>, value: T) -> Result<J> {
99 catch(|| self(scope, value).into_result())
100 }
101}
102
103impl<F, R, J, I, T, U> FlatMapFn<ForKey, J, I, T, U> for F
106where
107 F: Fn(&Key<I>) -> R + Send + 'static,
108 R: IntoResult<J>,
109 J: IntoIterator<Item = (Key<I>, U)>,
110 I: Display,
111{
112 type Iter = J;
113
114 #[cfg_attr(
115 feature = "tracing",
116 tracing::instrument(
117 level = "debug", skip_all, fields(key = %scope.key())
118 )
119 )]
120 #[inline]
121 fn execute(&self, scope: &mut Scope<I>, _: T) -> Result<J> {
122 catch(|| self(scope.key()).into_result())
123 }
124}
125
126impl<F, R, J, I, T, U> FlatMapFn<ForKeyValue, J, I, T, U> for F
127where
128 F: Fn(&Key<I>, T) -> R + Send + 'static,
129 R: IntoResult<J>,
130 J: IntoIterator<Item = (Key<I>, U)>,
131 I: Display,
132{
133 type Iter = J;
134
135 #[cfg_attr(
136 feature = "tracing",
137 tracing::instrument(
138 level = "debug", skip_all, fields(key = %scope.key())
139 )
140 )]
141 #[inline]
142 fn execute(&self, scope: &mut Scope<I>, value: T) -> Result<J> {
143 catch(|| self(scope.key(), value).into_result())
144 }
145}
146
147impl<F, R, J, I, T, U> FlatMapFn<ForId, J, I, T, U> for F
150where
151 F: Fn(&I) -> R + Send + 'static,
152 R: IntoResult<J>,
153 J: IntoIterator<Item = (Key<I>, U)>,
154 I: Display,
155{
156 type Iter = J;
157
158 #[cfg_attr(
159 feature = "tracing",
160 tracing::instrument(
161 level = "debug", skip_all, fields(key = %scope.key())
162 )
163 )]
164 #[inline]
165 fn execute(&self, scope: &mut Scope<I>, _: T) -> Result<J> {
166 catch(|| self(scope.key().try_as_id()?).into_result())
167 }
168}
169
170impl<F, R, J, I, T, U> FlatMapFn<ForIdValue, J, I, T, U> for F
171where
172 F: Fn(&I, T) -> R + Send + 'static,
173 R: IntoResult<J>,
174 J: IntoIterator<Item = (Key<I>, U)>,
175 I: Display,
176{
177 type Iter = J;
178
179 #[cfg_attr(
180 feature = "tracing",
181 tracing::instrument(
182 level = "debug", skip_all, fields(key = %scope.key())
183 )
184 )]
185 #[inline]
186 fn execute(&self, scope: &mut Scope<I>, value: T) -> Result<J> {
187 catch(|| self(scope.key().try_as_id()?, value).into_result())
188 }
189}
190
191impl<F, R, J, I, T, U> FlatMapFn<ForValue, J, I, T, U> for F
194where
195 F: Fn(T) -> R + Send + 'static,
196 R: IntoResult<J>,
197 J: IntoIterator<Item = (Key<I>, U)>,
198 I: Display,
199{
200 type Iter = J;
201
202 #[cfg_attr(
203 feature = "tracing",
204 tracing::instrument(
205 level = "debug", skip_all, fields(key = %scope.key())
206 )
207 )]
208 #[inline]
209 fn execute(&self, scope: &mut Scope<I>, value: T) -> Result<J> {
210 catch(|| self(value).into_result())
211 }
212}
213
214macro_rules! impl_flat_map_fn_for_scope_splat {
219 ($($T:ident),+) => {
220 impl<F, R, J, I, $($T,)+ U> FlatMapFn<ForScopeSplat, J, I, ($($T,)+), U>
221 for F
222 where
223 F: Fn(&mut Scope<I>, $($T),+) -> R + Send + 'static,
224 R: IntoResult<J>,
225 J: IntoIterator<Item = (Key<I>, U)>,
226 I: Display,
227 {
228 type Iter = J;
229
230 #[cfg_attr(
231 feature = "tracing",
232 tracing::instrument(
233 level = "debug", skip_all, fields(key = %scope.key())
234 )
235 )]
236 #[inline]
237 fn execute(
238 &self, scope: &mut Scope<I>, value: ($($T,)+),
239 ) -> Result<J> {
240 #[allow(non_snake_case)]
241 let ($($T,)+) = value;
242 catch(|| self(scope, $($T),+).into_result())
243 }
244 }
245 };
246}
247
248macro_rules! impl_flat_map_fn_for_key_splat {
249 ($($T:ident),+) => {
250 impl<F, R, J, I, $($T,)+ U> FlatMapFn<ForKeySplat, J, I, ($($T,)+), U>
251 for F
252 where
253 F: Fn(&Key<I>, $($T),+) -> R + Send + 'static,
254 R: IntoResult<J>,
255 J: IntoIterator<Item = (Key<I>, U)>,
256 I: Display,
257 {
258 type Iter = J;
259
260 #[cfg_attr(
261 feature = "tracing",
262 tracing::instrument(
263 level = "debug", skip_all, fields(key = %scope.key())
264 )
265 )]
266 #[inline]
267 fn execute(
268 &self, scope: &mut Scope<I>, value: ($($T,)+),
269 ) -> Result<J> {
270 #[allow(non_snake_case)]
271 let ($($T,)+) = value;
272 catch(|| self(scope.key(), $($T),+).into_result())
273 }
274 }
275 };
276}
277
278macro_rules! impl_flat_map_fn_for_id_splat {
279 ($($T:ident),+) => {
280 impl<F, R, J, I, $($T,)+ U> FlatMapFn<ForIdSplat, J, I, ($($T,)+), U>
281 for F
282 where
283 F: Fn(&I, $($T),+) -> R + Send + 'static,
284 R: IntoResult<J>,
285 J: IntoIterator<Item = (Key<I>, U)>,
286 I: Display,
287 {
288 type Iter = J;
289
290 #[cfg_attr(
291 feature = "tracing",
292 tracing::instrument(
293 level = "debug", skip_all, fields(key = %scope.key())
294 )
295 )]
296 #[inline]
297 fn execute(
298 &self, scope: &mut Scope<I>, value: ($($T,)+),
299 ) -> Result<J> {
300 #[allow(non_snake_case)]
301 let ($($T,)+) = value;
302 catch(|| self(scope.key().try_as_id()?, $($T),+).into_result())
303 }
304 }
305 };
306}
307
308macro_rules! impl_flat_map_fn_for_splat {
309 ($($T:ident),+) => {
310 impl<F, R, J, I, $($T,)+ U> FlatMapFn<ForSplat, J, I, ($($T,)+), U>
311 for F
312 where
313 F: Fn($($T),+) -> R + Send + 'static,
314 R: IntoResult<J>,
315 J: IntoIterator<Item = (Key<I>, U)>,
316 I: Display,
317 {
318 type Iter = J;
319
320 #[cfg_attr(
321 feature = "tracing",
322 tracing::instrument(
323 level = "debug", skip_all, fields(key = %scope.key())
324 )
325 )]
326 #[inline]
327 fn execute(
328 &self, scope: &mut Scope<I>, value: ($($T,)+),
329 ) -> Result<J> {
330 #[allow(non_snake_case)]
331 let ($($T,)+) = value;
332 catch(|| self($($T),+).into_result())
333 }
334 }
335 };
336}
337
338macro_rules! impl_flat_map_fn {
342 ($($T:ident),+) => {
343 impl_flat_map_fn_for_scope_splat!($($T),+);
344 impl_flat_map_fn_for_key_splat!($($T),+);
345 impl_flat_map_fn_for_id_splat!($($T),+);
346 impl_flat_map_fn_for_splat!($($T),+);
347 };
348}
349
350impl_flat_map_fn!(T1);
353impl_flat_map_fn!(T1, T2);
354impl_flat_map_fn!(T1, T2, T3);
355impl_flat_map_fn!(T1, T2, T3, T4);
356impl_flat_map_fn!(T1, T2, T3, T4, T5);
357impl_flat_map_fn!(T1, T2, T3, T4, T5, T6);
358impl_flat_map_fn!(T1, T2, T3, T4, T5, T6, T7);
359impl_flat_map_fn!(T1, T2, T3, T4, T5, T6, T7, T8);