Skip to main content

zrx_stream/stream/function/traits/
map.rs

1// Copyright (c) 2025-2026 Zensical and contributors
2
3// SPDX-License-Identifier: MIT
4// All contributions are certified under the DCO
5
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to
8// deal in the Software without restriction, including without limitation the
9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10// sell copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22// IN THE SOFTWARE.
23
24// ----------------------------------------------------------------------------
25
26//! Map function.
27
28use std::fmt::Display;
29
30use zrx_scheduler::step::Result;
31use zrx_scheduler::{Scope, Value};
32
33use crate::stream::function::adapter::WithSplat;
34use crate::stream::function::{catch, Splat};
35
36// ----------------------------------------------------------------------------
37// Traits
38// ----------------------------------------------------------------------------
39
40/// Map function.
41pub trait MapFn<I, T, U>: Send + 'static {
42    /// Executes the map function.
43    ///
44    /// # Errors
45    ///
46    /// This method returns an error if the function fails to execute.
47    fn execute(&self, scope: &Scope<I>, value: &T) -> Result<U>;
48}
49
50// ----------------------------------------------------------------------------
51// Blanket implementations
52// ----------------------------------------------------------------------------
53
54impl<F, I, T, U> MapFn<I, T, U> for F
55where
56    F: Fn(&T) -> Result<U> + Send + 'static,
57    I: Display,
58    T: Value,
59{
60    #[cfg_attr(
61        feature = "tracing",
62        tracing::instrument(level = "debug", skip_all, fields(id = %scope))
63    )]
64    #[inline]
65    fn execute(&self, scope: &Scope<I>, value: &T) -> Result<U> {
66        catch(|| self(value))
67    }
68}
69
70impl<F, I, T, U> MapFn<I, T, U> for WithSplat<F>
71where
72    F: MapFn<I, Splat<T>, U>,
73{
74    #[inline]
75    fn execute(&self, scope: &Scope<I>, value: &T) -> Result<U> {
76        F::execute(self, scope, Splat::from_ref(value))
77    }
78}
79
80// ----------------------------------------------------------------------------
81// Macros
82// ----------------------------------------------------------------------------
83
84/// Implements map function trait for splat arguments.
85macro_rules! impl_map_fn_for_splat {
86    ($($T:ident),+) => {
87        impl<F, I, $($T,)+ U> MapFn<I, Splat<($($T,)+)>, U> for F
88        where
89            F: Fn($(&$T),+) -> Result<U> + Send + 'static,
90            I: Display,
91        {
92            #[cfg_attr(
93                feature = "tracing",
94                tracing::instrument(
95                    level = "debug", skip_all, fields(id = %scope)
96                )
97            )]
98            #[inline]
99            fn execute(
100                &self, scope: &Scope<I>, value: &Splat<($($T,)+)>
101            ) -> Result<U> {
102                #[allow(non_snake_case)]
103                let ($($T,)+) = value.inner();
104                catch(|| self($($T),+))
105            }
106        }
107    };
108}
109
110// ----------------------------------------------------------------------------
111
112impl_map_fn_for_splat!(T1);
113impl_map_fn_for_splat!(T1, T2);
114impl_map_fn_for_splat!(T1, T2, T3);
115impl_map_fn_for_splat!(T1, T2, T3, T4);
116impl_map_fn_for_splat!(T1, T2, T3, T4, T5);
117impl_map_fn_for_splat!(T1, T2, T3, T4, T5, T6);
118impl_map_fn_for_splat!(T1, T2, T3, T4, T5, T6, T7);
119impl_map_fn_for_splat!(T1, T2, T3, T4, T5, T6, T7, T8);