floxide_core/
split.rs

1use crate::context::Context;
2use crate::error::FloxideError;
3use crate::node::Node;
4use crate::transition::Transition;
5use async_trait::async_trait;
6use std::marker::PhantomData;
7
8/// A node that splits its input into multiple outputs using the provided function.
9///
10/// Given an input `I`, the splitter function returns `Vec<O>`, and each element
11/// is emitted via a `Transition::NextAll` to the workflow engine.
12#[derive(Clone, Debug)]
13pub struct SplitNode<I, O, F>
14where
15    F: Fn(I) -> Vec<O> + Send + Sync,
16{
17    splitter: F,
18    _phantom: PhantomData<(I, O)>,
19}
20
21impl<I, O, F> SplitNode<I, O, F>
22where
23    F: Fn(I) -> Vec<O> + Send + Sync,
24{
25    /// Create a new SplitNode from a function that maps an input to a Vec of outputs.
26    pub fn new(splitter: F) -> Self {
27        SplitNode {
28            splitter,
29            _phantom: PhantomData,
30        }
31    }
32}
33
34#[async_trait]
35impl<C, I, O, F> Node<C> for SplitNode<I, O, F>
36where
37    C: Context,
38    I: Send + Sync + 'static,
39    O: Send + Sync + 'static,
40    F: Fn(I) -> Vec<O> + Send + Sync,
41{
42    /// Input type for the split node.
43    type Input = I;
44    /// Output type produced by the split node.
45    type Output = O;
46
47    /// Process an input value, producing multiple outputs via NextAll transition.
48    async fn process(&self, _ctx: &C, input: I) -> Result<Transition<O>, FloxideError> {
49        let outputs = (self.splitter)(input);
50        Ok(Transition::NextAll(outputs))
51    }
52}