1crate::ix!();
3
4#[derive(Builder,MutGetters,Setters,Getters,Debug,Clone)]
9#[builder(setter(into))]
10#[getset(get="pub",set = "pub", get_mut = "pub")]
11pub struct NetworkNode<NetworkItem>
12where NetworkItem: Debug + Send + Sync
13{
14 index: usize,
16
17 operator: Arc<dyn Operator<NetworkItem>>,
19
20 inputs: NetworkNodeIoChannelArray<NetworkItem>,
22
23 outputs: NetworkNodeIoChannelArray<NetworkItem>,
25}
26
27impl<NetworkItem> NetworkNode<NetworkItem>
28where NetworkItem: Debug + Send + Sync
29{
30 pub async fn execute(&self) -> NetResult<()> {
34
35 let mut read_guards: NetworkNodeIoChannelReadGuardArray<'_, NetworkItem>
37 = [None, None, None, None];
38
39 for i in 0..4 {
40 if let Some(arc) = &self.inputs[i] {
41 read_guards[i] = Some(arc.read().await);
42 }
43 }
44
45 let inputs: [Option<&NetworkItem>; 4] = [
47 read_guards[0].as_ref().map(|g| &**g),
48 read_guards[1].as_ref().map(|g| &**g),
49 read_guards[2].as_ref().map(|g| &**g),
50 read_guards[3].as_ref().map(|g| &**g),
51 ];
52
53 let mut output_buffer: NetworkNodeIoChannelValues<NetworkItem> =
55 [None, None, None, None];
56
57 self.operator.execute(inputs, &mut output_buffer).await?;
59
60 let mut write_guards: [Option<tokio::sync::RwLockWriteGuard<'_, NetworkItem>>; 4]
62 = [None, None, None, None];
63
64 for i in 0..4 {
65 if let Some(arc) = &self.outputs[i] {
66 write_guards[i] = Some(arc.write().await);
67 }
68 }
69
70 Self::finish_execution(write_guards, output_buffer)?;
72
73 Ok(())
74 }
75
76 fn finish_execution(mut output: NetworkNodeIoChannelWriteGuardArray<'_,NetworkItem>, mut values: NetworkNodeIoChannelValues<NetworkItem>) -> NetResult<()>
77 where NetworkItem: Debug + Send + Sync
78 {
79 if let Some(o0) = &mut output[0] { if let Some(v) = values[0].take() { **o0 = v; } }
80 if let Some(o1) = &mut output[1] { if let Some(v) = values[1].take() { **o1 = v; } }
81 if let Some(o2) = &mut output[2] { if let Some(v) = values[2].take() { **o2 = v; } }
82 if let Some(o3) = &mut output[3] { if let Some(v) = values[3].take() { **o3 = v; } }
83 Ok(())
84 }
85}
86
87#[macro_export]
88macro_rules! node {
89 ($idx:expr => $op:expr) => {
90 NetworkNodeBuilder::default()
91 .index($idx as usize)
92 .operator($op.into_arc_operator())
93 .inputs([None, None, None, None])
94 .outputs([None, None, None, None])
95 .build()
96 .unwrap()
97 };
98}
99
100#[cfg(test)]
101mod node_macro_tests {
102 use super::*;
103
104 #[test]
105 fn test_node_macro_single_noop() {
106 let n0: NetworkNode<TestWireIO<i32>> = node!(0 => NoOpOperator::default());
108 assert_eq!(*n0.index(), 0);
109 assert_eq!(n0.operator().name(), "default");
110 for i in 0..4 {
112 assert!(n0.inputs()[i].is_none(), "Expected no inputs yet");
113 assert!(n0.outputs()[i].is_none(), "Expected no outputs yet");
114 }
115 }
116
117 #[test]
118 fn test_node_macro_with_custom_operator() {
119 let n7: NetworkNode<TestWireIO<i32>> = node!(7 => AddOp::new(7));
121 assert_eq!(*n7.index(), 7);
122 assert_eq!(n7.operator().name(), "AddOp(+7)");
123 for i in 0..4 {
125 assert!(n7.inputs()[i].is_none());
126 assert!(n7.outputs()[i].is_none());
127 }
128 }
129}