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 GetFn<A, I, T, U>: Send + 'static {
46 fn execute(&self, scope: &mut Scope<I>, value: &T) -> Result<U>;
52}
53
54impl<F, R, I, T, U> GetFn<ForScope, I, T, U> for F
59where
60 F: Fn(&mut Scope<I>) -> R + Send + 'static,
61 R: IntoResult<U>,
62 I: Display,
63{
64 #[cfg_attr(
65 feature = "tracing",
66 tracing::instrument(
67 level = "debug", skip_all, fields(key = %scope.key())
68 )
69 )]
70 #[inline]
71 fn execute(&self, scope: &mut Scope<I>, _: &T) -> Result<U> {
72 catch(|| self(scope).into_result())
73 }
74}
75
76impl<F, R, I, T, U> GetFn<ForScopeValue, I, T, U> for F
77where
78 F: Fn(&mut Scope<I>, &T) -> R + Send + 'static,
79 R: IntoResult<U>,
80 I: Display,
81{
82 #[cfg_attr(
83 feature = "tracing",
84 tracing::instrument(
85 level = "debug", skip_all, fields(key = %scope.key())
86 )
87 )]
88 #[inline]
89 fn execute(&self, scope: &mut Scope<I>, value: &T) -> Result<U> {
90 catch(|| self(scope, value).into_result())
91 }
92}
93
94impl<F, R, I, T, U> GetFn<ForKey, I, T, U> for F
97where
98 F: Fn(&Key<I>) -> R + Send + 'static,
99 R: IntoResult<U>,
100 I: Display,
101{
102 #[cfg_attr(
103 feature = "tracing",
104 tracing::instrument(
105 level = "debug", skip_all, fields(key = %scope.key())
106 )
107 )]
108 #[inline]
109 fn execute(&self, scope: &mut Scope<I>, _: &T) -> Result<U> {
110 catch(|| self(scope.key()).into_result())
111 }
112}
113
114impl<F, R, I, T, U> GetFn<ForKeyValue, I, T, U> for F
115where
116 F: Fn(&Key<I>, &T) -> R + Send + 'static,
117 R: IntoResult<U>,
118 I: Display,
119{
120 #[cfg_attr(
121 feature = "tracing",
122 tracing::instrument(
123 level = "debug", skip_all, fields(key = %scope.key())
124 )
125 )]
126 #[inline]
127 fn execute(&self, scope: &mut Scope<I>, value: &T) -> Result<U> {
128 catch(|| self(scope.key(), value).into_result())
129 }
130}
131
132impl<F, R, I, T, U> GetFn<ForId, I, T, U> for F
135where
136 F: Fn(&I) -> R + Send + 'static,
137 R: IntoResult<U>,
138 I: Display,
139{
140 #[cfg_attr(
141 feature = "tracing",
142 tracing::instrument(
143 level = "debug", skip_all, fields(key = %scope.key())
144 )
145 )]
146 #[inline]
147 fn execute(&self, scope: &mut Scope<I>, _: &T) -> Result<U> {
148 catch(|| self(scope.key().try_as_id()?).into_result())
149 }
150}
151
152impl<F, R, I, T, U> GetFn<ForIdValue, I, T, U> for F
153where
154 F: Fn(&I, &T) -> R + Send + 'static,
155 R: IntoResult<U>,
156 I: Display,
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>, value: &T) -> Result<U> {
166 catch(|| self(scope.key().try_as_id()?, value).into_result())
167 }
168}
169
170impl<F, R, I, T, U> GetFn<ForValue, I, T, U> for F
173where
174 F: Fn(&T) -> R + Send + 'static,
175 R: IntoResult<U>,
176 I: Display,
177{
178 #[cfg_attr(
179 feature = "tracing",
180 tracing::instrument(
181 level = "debug", skip_all, fields(key = %scope.key())
182 )
183 )]
184 #[inline]
185 fn execute(&self, scope: &mut Scope<I>, value: &T) -> Result<U> {
186 catch(|| self(value).into_result())
187 }
188}
189
190macro_rules! impl_get_fn_for_scope_splat {
196 ($($T:ident),+) => {
197 impl<F, R, I, $($T,)+ U> GetFn<ForScopeSplat, I, ($($T,)+), U> for F
198 where
199 F: Fn(&mut Scope<I>, $(&$T),+) -> R + Send + 'static,
200 R: IntoResult<U>,
201 I: Display,
202 {
203 #[cfg_attr(
204 feature = "tracing",
205 tracing::instrument(
206 level = "debug", skip_all, fields(key = %scope.key())
207 )
208 )]
209 #[inline]
210 fn execute(
211 &self, scope: &mut Scope<I>, value: &($($T,)+)
212 ) -> Result<U> {
213 #[allow(non_snake_case)]
214 let ($($T,)+) = value;
215 catch(|| self(scope, $($T),+).into_result())
216 }
217 }
218 };
219}
220
221macro_rules! impl_get_fn_for_key_splat {
223 ($($T:ident),+) => {
224 impl<F, R, I, $($T,)+ U> GetFn<ForKeySplat, I, ($($T,)+), U> for F
225 where
226 F: Fn(&Key<I>, $(&$T),+) -> R + Send + 'static,
227 R: IntoResult<U>,
228 I: Display,
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<U> {
240 #[allow(non_snake_case)]
241 let ($($T,)+) = value;
242 catch(|| self(scope.key(), $($T),+).into_result())
243 }
244 }
245 };
246}
247
248macro_rules! impl_get_fn_for_id_splat {
250 ($($T:ident),+) => {
251 impl<F, R, I, $($T,)+ U> GetFn<ForIdSplat, I, ($($T,)+), U> for F
252 where
253 F: Fn(&I, $(&$T),+) -> R + Send + 'static,
254 R: IntoResult<U>,
255 I: Display,
256 {
257 #[cfg_attr(
258 feature = "tracing",
259 tracing::instrument(
260 level = "debug", skip_all, fields(key = %scope.key())
261 )
262 )]
263 #[inline]
264 fn execute(
265 &self, scope: &mut Scope<I>, value: &($($T,)+)
266 ) -> Result<U> {
267 #[allow(non_snake_case)]
268 let ($($T,)+) = value;
269 catch(|| self(scope.key().try_as_id()?, $($T),+).into_result())
270 }
271 }
272 };
273}
274
275macro_rules! impl_get_fn_for_splat {
277 ($($T:ident),+) => {
278 impl<F, R, I, $($T,)+ U> GetFn<ForSplat, I, ($($T,)+), U> for F
279 where
280 F: Fn($(&$T),+) -> R + Send + 'static,
281 R: IntoResult<U>,
282 I: Display,
283 {
284 #[cfg_attr(
285 feature = "tracing",
286 tracing::instrument(
287 level = "debug", skip_all, fields(key = %scope.key())
288 )
289 )]
290 #[inline]
291 fn execute(
292 &self, scope: &mut Scope<I>, value: &($($T,)+)
293 ) -> Result<U> {
294 #[allow(non_snake_case)]
295 let ($($T,)+) = value;
296 catch(|| self($($T),+).into_result())
297 }
298 }
299 };
300}
301
302macro_rules! impl_get_fn {
306 ($($T:ident),+) => {
307 impl_get_fn_for_scope_splat!($($T),+);
308 impl_get_fn_for_key_splat!($($T),+);
309 impl_get_fn_for_id_splat!($($T),+);
310 impl_get_fn_for_splat!($($T),+);
311 };
312}
313
314impl_get_fn!(T1);
317impl_get_fn!(T1, T2);
318impl_get_fn!(T1, T2, T3);
319impl_get_fn!(T1, T2, T3, T4);
320impl_get_fn!(T1, T2, T3, T4, T5);
321impl_get_fn!(T1, T2, T3, T4, T5, T6);
322impl_get_fn!(T1, T2, T3, T4, T5, T6, T7);
323impl_get_fn!(T1, T2, T3, T4, T5, T6, T7, T8);