iridis_layout/
node.rs

1//! This module defines the layout of everything related to a `Node`.
2
3use std::collections::{HashMap, HashSet};
4
5use crate::prelude::*;
6
7/// A unique identifier for a node in the graph, it's
8/// composed of a label and a UUID. By design the only thing
9/// the runtime needs to know about a node is its UUID. But for
10/// debugging purposes, we also keep the label.
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub struct NodeID {
13    pub label: String,
14    pub uuid: Uuid,
15}
16
17impl NodeID {
18    /// Creates a new `NodeID` with a random UUID and the given label.
19    pub fn new(label: impl Into<String>) -> Self {
20        NodeID {
21            label: label.into(),
22            uuid: Uuid::new_v4(),
23        }
24    }
25
26    /// Creates a new `InputID` with the given label. The UUID is
27    /// generated from its label and the node's UUID.
28    pub fn input(&self, input: impl Into<String>) -> InputID {
29        let label = input.into();
30
31        InputID {
32            uuid: Uuid::new_v3(&self.uuid, label.as_bytes()),
33            label,
34        }
35    }
36
37    /// Creates a new `OutputID` with the given label. The UUID is
38    /// generated from its label and the node's UUID.
39    pub fn output(&self, output: impl Into<String>) -> OutputID {
40        let label = output.into();
41
42        OutputID {
43            uuid: Uuid::new_v3(&self.uuid, label.as_bytes()),
44            label,
45        }
46    }
47
48    /// Creates a new `QueryID` with the given label. The UUID is
49    /// generated from its label and the node's UUID.
50    pub fn query(&self, query: impl Into<String>) -> QueryID {
51        let label = query.into();
52
53        QueryID {
54            uuid: Uuid::new_v3(&self.uuid, label.as_bytes()),
55            label,
56        }
57    }
58
59    /// Creates a new `QueryableID` with the given label. The UUID is
60    /// generated from its label and the node's UUID.
61    pub fn queryable(&self, queryable: impl Into<String>) -> QueryableID {
62        let label = queryable.into();
63
64        QueryableID {
65            uuid: Uuid::new_v3(&self.uuid, label.as_bytes()),
66            label,
67        }
68    }
69}
70
71/// For internal use, this struct represents all the primitives
72/// belonging to a node. It is used to create the layout of the node.
73pub struct NodeDataLayout {
74    pub inputs: HashSet<Uuid>,
75    pub outputs: HashSet<Uuid>,
76    pub queries: HashSet<Uuid>,
77    pub queryables: HashSet<Uuid>,
78}
79
80/// For internal use, this struct represents the debug layout of a node.
81/// It is used to store the labels of the primitives in the node.
82pub struct NodeDebugLayout {
83    pub labels: HashMap<Uuid, String>,
84}
85
86/// For internal use, this struct represents the layout of a node, both
87/// the data and the debug layout.
88pub struct NodeLayout {
89    pub id: NodeID,
90    pub data: NodeDataLayout,
91    pub debug: NodeDebugLayout,
92}
93
94impl NodeLayout {
95    /// Creates a new empty `NodeLayout` with the given `NodeID`.
96    pub fn new(id: &NodeID) -> Self {
97        Self {
98            id: id.clone(),
99            data: NodeDataLayout {
100                inputs: HashSet::new(),
101                outputs: HashSet::new(),
102                queries: HashSet::new(),
103                queryables: HashSet::new(),
104            },
105            debug: NodeDebugLayout {
106                labels: HashMap::new(),
107            },
108        }
109    }
110
111    /// Adds a new input to the node layout. It returns a generic
112    /// enum `PrimitiveID` that can be used to identify the input.
113    pub fn input(&mut self, input: impl Into<String>) -> PrimitiveID {
114        let label: String = input.into();
115        let layout = self.id.input(&label);
116
117        self.data.inputs.insert(layout.uuid);
118
119        self.debug.labels.insert(layout.uuid, label.clone());
120
121        tracing::debug!(
122            "Node '{}' (uuid: {}) added input layout with label: '{}' (uuid: {})",
123            self.id.label,
124            self.id.uuid,
125            label,
126            layout.uuid
127        );
128
129        layout.into()
130    }
131
132    /// Adds a new output to the node layout. It returns a generic
133    /// enum `PrimitiveID` that can be used to identify the output.
134    pub fn output(&mut self, output: impl Into<String>) -> PrimitiveID {
135        let label: String = output.into();
136        let layout = self.id.output(&label);
137
138        self.data.outputs.insert(layout.uuid);
139
140        self.debug.labels.insert(layout.uuid, label.clone());
141
142        tracing::debug!(
143            "Node '{}' (uuid: {}) added output layout with label: '{}' (uuid: {})",
144            self.id.label,
145            self.id.uuid,
146            label,
147            layout.uuid
148        );
149
150        layout.into()
151    }
152
153    /// Adds a new query to the node layout. It returns a generic
154    /// enum `PrimitiveID` that can be used to identify the query.
155    pub fn query(&mut self, query: impl Into<String>) -> PrimitiveID {
156        let label: String = query.into();
157        let layout = self.id.query(&label);
158
159        self.data.queries.insert(layout.uuid);
160
161        self.debug.labels.insert(layout.uuid, label.clone());
162
163        tracing::debug!(
164            "Node '{}' (uuid: {}) added query layout with label: '{}' (uuid: {})",
165            self.id.label,
166            self.id.uuid,
167            label,
168            layout.uuid
169        );
170
171        layout.into()
172    }
173
174    /// Adds a new queryable to the node layout. It returns a generic
175    /// enum `PrimitiveID` that can be used to identify the queryable.
176    pub fn queryable(&mut self, queryable: impl Into<String>) -> PrimitiveID {
177        let label: String = queryable.into();
178        let layout = self.id.queryable(&label);
179
180        self.data.queryables.insert(layout.uuid);
181
182        self.debug.labels.insert(layout.uuid, label.clone());
183
184        tracing::debug!(
185            "Node '{}' (uuid: {}) added queryable layout with label: '{}' (uuid: {})",
186            self.id.label,
187            self.id.uuid,
188            label,
189            layout.uuid
190        );
191
192        layout.into()
193    }
194}