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}