node_flow/node/macros.rs
1/// Implements the [`Node`](crate::node::Node) trait for a type whose output
2/// needs to be wrapped in [`NodeOutput`](crate::node::NodeOutput).
3///
4/// It automatically generates an implementation of:
5/// ```ignore
6/// impl<Context> Node<Input, NodeOutput<Output>, Error, Context> for NodeType
7/// ```
8/// From an existing implementation of:
9/// ```ignore
10/// impl<Context> Node<Input, Output, Error, Context> for NodeType
11/// ```
12///
13/// This macro adds a `Node` implementation that returns `NodeOutput<T>`.
14/// It works by wrapping an existing implementation of `Node` that returns `Output`,
15/// turning it into `NodeOutput<Output>`.
16///
17/// # Parameters
18/// - `$node`: The node type to add an implementation for.
19/// - `$input`, `$output`, `$error`: Input, Output and Error type parameters for the node.
20/// - `$param: $bound0 + $bound`: Optional trait bounds for generics.
21///
22/// See also [`Node`](crate::node::Node), [`NodeOutput`](crate::node::NodeOutput).
23///
24/// # Examples
25/// ```
26/// use node_flow::{impl_node_output, node::{Node, NodeOutput}};
27///
28/// struct ExampleNode;
29///
30/// impl<Context: Send> Node<i32, i32, String, Context> for ExampleNode {
31/// async fn run(&mut self, input: i32, _context: &mut Context) -> Result<i32, String> {
32/// Ok(input + 1)
33/// }
34/// }
35///
36/// // Automatically implement Node<i32, NodeOutput<i32>, String, _> for ExampleNode.
37/// impl_node_output!(ExampleNode, i32, i32, String);
38/// ```
39#[macro_export]
40macro_rules! impl_node_output {
41 ($node:ty, $input:ty, $output:ty, $error:ty $(,$param:ident: $bound0:ident $(+$bound:ident)*)*) => {
42 impl<Context>
43 $crate::node::Node<$input, $crate::node::NodeOutput<$output>, $error, Context>
44 for $node
45 where
46 Context: Send,
47 $($param: $bound0 $(+$bound)*,)*
48 {
49 async fn run(
50 &mut self,
51 input: $input,
52 context: &mut Context,
53 ) -> Result<$crate::node::NodeOutput<$output>, $error> {
54 Ok($crate::node::NodeOutput::Ok(
55 <Self as $crate::node::Node<$input, $output, $error, Context>>::run(
56 self, input, context,
57 )
58 .await?,
59 ))
60 }
61
62 fn describe(&self) -> $crate::describe::Description {
63 <Self as $crate::node::Node<$input, $output, $error, Context>>::describe(self)
64 }
65 }
66 };
67}
68
69/// A helper macro for declaring [`impl Node`](crate::node::Node) return type.
70///
71/// Use `!` before an output type for it to **not** be wrapped in [`NodeOutput`](crate::node::NodeOutput).
72///
73/// # Parameters
74/// - `$input`: The input type accepted by the node.
75/// - `$output`: The output type (raw or wrapped) returned by the node.
76/// - `$error`: The error type returned by the node.
77/// - `$context`: The context type passed to the node.
78///
79/// See also [`Node`](crate::node::Node), [`NodeOutput`](crate::node::NodeOutput).
80///
81/// # Examples
82/// ```
83/// use node_flow::node::Node;
84///
85/// #[derive(Clone)]
86/// struct ExampleNode;
87/// impl<Context: Send> Node<u8, u64, String, Context> for ExampleNode // ...
88/// # {
89/// # async fn run(
90/// # &mut self,
91/// # input: u8,
92/// # _context: &mut Context,
93/// # ) -> Result<u64, String> {
94/// # Ok(input as u64)
95/// # }
96/// # }
97///
98/// fn build_flow<Context: Send>() -> node_flow::node!(u8, !u64, String, Context) {
99/// ExampleNode
100/// }
101/// ```
102///
103/// # Expansion
104/// ```ignore
105/// node!($input, $output, $error, $context)
106/// // expands to:
107/// impl node_flow::node::Node<
108/// $input,
109/// node_flow::node::NodeOutput<$output>,
110/// $error,
111/// $context
112/// > + Clone + Send + Sync
113/// ```
114/// By adding `!` to output the raw `$output` type is used:
115/// ```ignore
116/// node!($input, !$output, $error, $context)
117/// // expands to:
118/// impl node_flow::node::Node<$input, $output, $error, $context> + Clone + Send + Sync
119/// ```
120#[macro_export]
121macro_rules! node {
122 ($input:ty, !$output:ty, $error:ty, $context:ty) => {
123 impl $crate::node::Node<$input, $output, $error, $context> + Clone + Send + Sync
124 };
125 ($input:ty, $output:ty, $error:ty, $context:ty) => {
126 $crate::node!($input, !$crate::node::NodeOutput<$output>, $error, $context)
127 };
128}