node_flow/node/
boxed.rs

1use crate::{describe::Description, node::Node};
2
3/// The `BoxedNode` trait is a dyn compatible wrapper around the [`Node`] trait.
4///
5/// `BoxedNode` trait provides the same functions as the [`Node`] trait
6/// with the addition of dyn compatibility.
7/// This allows you to use `Box<dyn BoxedNode<...>>`.
8///
9/// Blanket implementation of [`BoxedNode`] is implemented
10/// for all types that implement [`Node`] trait.
11///
12/// See also [`Node`].
13///
14/// # Examples
15/// ```
16/// use node_flow::node::BoxedNode;
17///
18/// async fn run_node(
19///     node: &mut dyn BoxedNode<String, String, String, ()>,
20/// ) {
21///     let result = node.run_boxed("hello".into(), &mut ()).await;
22///     println!("{:?}", result);
23/// }
24/// ```
25#[async_trait::async_trait]
26pub trait BoxedNode<Input, Output, Error, Context> {
27    /// Runs the node.
28    ///
29    /// This method is equivalent to [`Node::run`], but allows calling it
30    /// via a `Box<dyn BoxedNode<...>>` trait object.
31    ///
32    /// # Returns
33    /// Boxed dyn [`Future`] (`Pin<Box<dyn Future<...> + Send + '_>>`) that resolves to a `Result<Output, Error>`.
34    ///
35    /// See also [`Node::run`].
36    async fn run_boxed(&mut self, input: Input, context: &mut Context) -> Result<Output, Error>
37    where
38        Input: 'async_trait,
39        Output: 'async_trait,
40        Error: 'async_trait;
41
42    /// Describes this node, its type signature and other specifics.
43    ///
44    /// See [`Description`] for more details.
45    /// See also [`Node::describe`].
46    fn describe(&self) -> Description;
47}
48
49impl<Input, Output, Error, Context, T> BoxedNode<Input, Output, Error, Context> for T
50where
51    T: Node<Input, Output, Error, Context>,
52{
53    fn run_boxed<'life0, 'life1, 'async_trait>(
54        &'life0 mut self,
55        input: Input,
56        context: &'life1 mut Context,
57    ) -> ::core::pin::Pin<
58        Box<
59            dyn ::core::future::Future<Output = Result<Output, Error>>
60                + ::core::marker::Send
61                + 'async_trait,
62        >,
63    >
64    where
65        Input: 'async_trait,
66        Output: 'async_trait,
67        Error: 'async_trait,
68        'life0: 'async_trait,
69        'life1: 'async_trait,
70        Self: 'async_trait,
71    {
72        Box::pin(<Self as Node<Input, Output, Error, Context>>::run(
73            self, input, context,
74        ))
75    }
76
77    fn describe(&self) -> Description {
78        <Self as Node<Input, Output, Error, Context>>::describe(self)
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use crate::node::NodeOutput;
85
86    use super::BoxedNode;
87
88    #[tokio::test]
89    async fn works() {
90        let n = crate::flows::tests::Passer::<u8, u16, ()>::new();
91        let mut b: Box<dyn BoxedNode<_, _, _, _>> = Box::new(n);
92        let res = b.run_boxed(5u8, &mut ()).await;
93        assert_eq!(res, Ok(NodeOutput::Ok(5u16)));
94    }
95}