1use std::collections::{HashMap, HashSet};
2
3use crate::prelude::*;
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7pub struct NodeLayout {
8    pub label: String,
9    pub uuid: Uuid,
10}
11
12impl NodeLayout {
13    pub fn new(label: impl Into<String>) -> Self {
15        NodeLayout {
16            label: label.into(),
17            uuid: Uuid::new_v4(),
18        }
19    }
20
21    pub fn input(&self, input: impl Into<String>) -> InputLayout {
23        let label = input.into();
24        InputLayout {
25            uuid: Uuid::new_v3(&self.uuid, label.as_bytes()),
26            label,
27        }
28    }
29
30    pub fn output(&self, output: impl Into<String>) -> OutputLayout {
32        let label = output.into();
33        OutputLayout {
34            uuid: Uuid::new_v3(&self.uuid, label.as_bytes()),
35            label,
36        }
37    }
38
39    pub fn query(&self, query: impl Into<String>) -> QueryLayout {
41        let label = query.into();
42        QueryLayout {
43            uuid: Uuid::new_v3(&self.uuid, label.as_bytes()),
44            label,
45        }
46    }
47
48    pub fn queryable(&self, queryable: impl Into<String>) -> QueryableLayout {
50        let label = queryable.into();
51        QueryableLayout {
52            uuid: Uuid::new_v3(&self.uuid, label.as_bytes()),
53            label,
54        }
55    }
56}
57
58pub struct NodeIOBuilder {
60    pub layout: NodeLayout,
62
63    pub inputs: HashSet<Uuid>,
65    pub outputs: HashSet<Uuid>,
67    pub queries: HashSet<Uuid>,
69    pub queryables: HashSet<Uuid>,
71
72    pub labels: HashMap<Uuid, String>,
74}
75
76impl NodeIOBuilder {
77    pub fn new(layout: &NodeLayout) -> Self {
78        Self {
79            layout: layout.clone(),
80
81            inputs: HashSet::new(),
82            outputs: HashSet::new(),
83            queryables: HashSet::new(),
84            queries: HashSet::new(),
85
86            labels: HashMap::new(),
87        }
88    }
89
90    pub fn input(&mut self, input: impl Into<String>) -> IOLayout {
92        let label: String = input.into();
93        let layout = self.layout.input(&label);
94
95        self.inputs.insert(layout.uuid);
96
97        self.labels.insert(layout.uuid, label.clone());
98
99        tracing::debug!(
100            "Node '{}' (uuid: {}) added input layout with label: '{}' (uuid: {})",
101            self.layout.label,
102            self.layout.uuid,
103            label,
104            layout.uuid
105        );
106
107        layout.into()
108    }
109
110    pub fn output(&mut self, output: impl Into<String>) -> IOLayout {
112        let label: String = output.into();
113        let layout = self.layout.output(&label);
114
115        self.outputs.insert(layout.uuid);
116
117        self.labels.insert(layout.uuid, label.clone());
118
119        tracing::debug!(
120            "Node '{}' (uuid: {}) added output layout with label: '{}' (uuid: {})",
121            self.layout.label,
122            self.layout.uuid,
123            label,
124            layout.uuid
125        );
126
127        layout.into()
128    }
129
130    pub fn query(&mut self, query: impl Into<String>) -> IOLayout {
132        let label: String = query.into();
133        let layout = self.layout.query(&label);
134
135        self.queries.insert(layout.uuid);
136
137        self.labels.insert(layout.uuid, label.clone());
138
139        tracing::debug!(
140            "Node '{}' (uuid: {}) added query layout with label: '{}' (uuid: {})",
141            self.layout.label,
142            self.layout.uuid,
143            label,
144            layout.uuid
145        );
146
147        layout.into()
148    }
149
150    pub fn queryable(&mut self, queryable: impl Into<String>) -> IOLayout {
152        let label: String = queryable.into();
153        let layout = self.layout.queryable(&label);
154
155        self.queryables.insert(layout.uuid);
156
157        self.labels.insert(layout.uuid, label.clone());
158
159        tracing::debug!(
160            "Node '{}' (uuid: {}) added queryable layout with label: '{}' (uuid: {})",
161            self.layout.label,
162            self.layout.uuid,
163            label,
164            layout.uuid
165        );
166
167        layout.into()
168    }
169}