1use std::{
2 collections::{HashMap, HashSet},
3 fmt,
4 sync::Arc,
5};
6
7use crate::prelude::*;
8
9pub struct DataflowLayout {
11 pub inputs: HashSet<Uuid>,
13 pub outputs: HashSet<Uuid>,
15 pub queries: HashSet<Uuid>,
17 pub queryables: HashSet<Uuid>,
19
20 pub labels: HashMap<Uuid, String>,
22 pub nodes: HashMap<Uuid, HashSet<Uuid>>,
24}
25
26impl Default for DataflowLayout {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32impl DataflowLayout {
33 pub fn new() -> Self {
35 Self {
36 inputs: HashSet::new(),
37 outputs: HashSet::new(),
38 queryables: HashSet::new(),
39 queries: HashSet::new(),
40
41 labels: HashMap::new(),
42 nodes: HashMap::new(),
43 }
44 }
45
46 pub async fn node<T>(
49 &mut self,
50 label: impl Into<String>,
51 builder_function: impl AsyncFnOnce(&mut NodeIOBuilder) -> T,
52 ) -> (NodeLayout, T) {
53 let label = label.into();
54 let layout = NodeLayout::new(&label);
55 let mut io = NodeIOBuilder::new(&layout);
56
57 let result = builder_function(&mut io).await;
58
59 self.nodes.insert(
60 layout.uuid,
61 io.inputs
62 .union(&io.outputs)
63 .chain(io.queries.union(&io.queryables))
64 .cloned()
65 .collect(),
66 );
67
68 self.inputs.extend(io.inputs);
69 self.outputs.extend(io.outputs);
70 self.queries.extend(io.queries);
71 self.queryables.extend(io.queryables);
72 self.labels.extend(io.labels);
73
74 self.labels.insert(layout.uuid, label.clone());
75
76 tracing::debug!("Node '{}' (uuid: {}) created", label, layout.uuid);
77
78 (layout, result)
79 }
80
81 pub fn label(&self, uuid: impl Into<Uuid>) -> String {
83 let uuid = uuid.into();
84
85 self.labels.get(&uuid).cloned().unwrap_or_default()
86 }
87
88 pub fn build(self) -> Arc<Self> {
90 Arc::new(self)
91 }
92}
93
94impl fmt::Debug for DataflowLayout {
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 #[derive(Debug)]
97 struct Layout {
98 #[allow(dead_code)]
99 id: (String, Uuid),
100
101 inputs: HashSet<(String, Uuid)>,
102 outputs: HashSet<(String, Uuid)>,
103 queryables: HashSet<(String, Uuid)>,
104 queries: HashSet<(String, Uuid)>,
105 }
106
107 let mut nodes = Vec::new();
108
109 for (&node, io) in &self.nodes {
110 let mut layout = Layout {
111 id: (self.label(node), node),
112
113 inputs: HashSet::new(),
114 outputs: HashSet::new(),
115 queryables: HashSet::new(),
116 queries: HashSet::new(),
117 };
118
119 for &io in io {
120 if self.inputs.contains(&io) {
121 layout.inputs.insert((self.label(io), io));
122 }
123 if self.outputs.contains(&io) {
124 layout.outputs.insert((self.label(io), io));
125 }
126 if self.queryables.contains(&io) {
127 layout.queryables.insert((self.label(io), io));
128 }
129 if self.queries.contains(&io) {
130 layout.queries.insert((self.label(io), io));
131 }
132 }
133
134 nodes.push(layout);
135 }
136
137 writeln!(f, "{:#?}", nodes)
138 }
139}