oximedia_graph/
node_registry.rs1#![allow(dead_code)]
7
8use std::collections::HashMap;
9
10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub enum NodeKind {
13 Source,
15 Filter,
17 Sink,
19 Mux,
21}
22
23impl NodeKind {
24 pub fn is_source(&self) -> bool {
26 *self == NodeKind::Source
27 }
28
29 pub fn is_sink(&self) -> bool {
31 *self == NodeKind::Sink
32 }
33
34 pub fn label(&self) -> &'static str {
36 match self {
37 NodeKind::Source => "source",
38 NodeKind::Filter => "filter",
39 NodeKind::Sink => "sink",
40 NodeKind::Mux => "mux",
41 }
42 }
43}
44
45#[derive(Debug, Clone)]
47pub struct GraphNode {
48 id: u64,
50 name: String,
52 kind: NodeKind,
54 enabled: bool,
56}
57
58impl GraphNode {
59 pub fn new(id: u64, name: impl Into<String>, kind: NodeKind) -> Self {
61 Self {
62 id,
63 name: name.into(),
64 kind,
65 enabled: true,
66 }
67 }
68
69 pub fn id(&self) -> u64 {
71 self.id
72 }
73
74 pub fn name(&self) -> &str {
76 &self.name
77 }
78
79 pub fn kind(&self) -> &NodeKind {
81 &self.kind
82 }
83
84 pub fn is_enabled(&self) -> bool {
86 self.enabled
87 }
88
89 pub fn set_enabled(&mut self, enabled: bool) {
91 self.enabled = enabled;
92 }
93}
94
95#[derive(Debug, Clone, Default)]
97pub struct NodeRegistry {
98 nodes: HashMap<u64, GraphNode>,
99 next_id: u64,
100}
101
102impl NodeRegistry {
103 pub fn new() -> Self {
105 Self {
106 nodes: HashMap::new(),
107 next_id: 0,
108 }
109 }
110
111 pub fn add(&mut self, name: impl Into<String>, kind: NodeKind) -> u64 {
114 let id = self.next_id;
115 self.next_id += 1;
116 self.nodes.insert(id, GraphNode::new(id, name, kind));
117 id
118 }
119
120 pub fn get(&self, id: u64) -> Option<&GraphNode> {
122 self.nodes.get(&id)
123 }
124
125 pub fn get_mut(&mut self, id: u64) -> Option<&mut GraphNode> {
127 self.nodes.get_mut(&id)
128 }
129
130 pub fn find_by_kind(&self, kind: &NodeKind) -> Vec<&GraphNode> {
132 self.nodes.values().filter(|n| n.kind() == kind).collect()
133 }
134
135 pub fn enabled_count(&self) -> usize {
137 self.nodes.values().filter(|n| n.is_enabled()).count()
138 }
139
140 pub fn len(&self) -> usize {
142 self.nodes.len()
143 }
144
145 pub fn is_empty(&self) -> bool {
147 self.nodes.is_empty()
148 }
149
150 pub fn remove(&mut self, id: u64) -> Option<GraphNode> {
152 self.nodes.remove(&id)
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn test_node_kind_is_source() {
162 assert!(NodeKind::Source.is_source());
163 assert!(!NodeKind::Sink.is_source());
164 }
165
166 #[test]
167 fn test_node_kind_is_sink() {
168 assert!(NodeKind::Sink.is_sink());
169 assert!(!NodeKind::Filter.is_sink());
170 }
171
172 #[test]
173 fn test_node_kind_label() {
174 assert_eq!(NodeKind::Source.label(), "source");
175 assert_eq!(NodeKind::Filter.label(), "filter");
176 assert_eq!(NodeKind::Sink.label(), "sink");
177 assert_eq!(NodeKind::Mux.label(), "mux");
178 }
179
180 #[test]
181 fn test_graph_node_enabled_by_default() {
182 let n = GraphNode::new(0, "node0", NodeKind::Source);
183 assert!(n.is_enabled());
184 }
185
186 #[test]
187 fn test_graph_node_set_enabled() {
188 let mut n = GraphNode::new(0, "node0", NodeKind::Filter);
189 n.set_enabled(false);
190 assert!(!n.is_enabled());
191 }
192
193 #[test]
194 fn test_registry_add_returns_incremental_ids() {
195 let mut reg = NodeRegistry::new();
196 let id0 = reg.add("a", NodeKind::Source);
197 let id1 = reg.add("b", NodeKind::Sink);
198 assert_eq!(id0, 0);
199 assert_eq!(id1, 1);
200 }
201
202 #[test]
203 fn test_registry_get() {
204 let mut reg = NodeRegistry::new();
205 let id = reg.add("scaler", NodeKind::Filter);
206 let node = reg.get(id).expect("get should succeed");
207 assert_eq!(node.name(), "scaler");
208 assert_eq!(node.kind(), &NodeKind::Filter);
209 }
210
211 #[test]
212 fn test_registry_find_by_kind() {
213 let mut reg = NodeRegistry::new();
214 reg.add("src1", NodeKind::Source);
215 reg.add("src2", NodeKind::Source);
216 reg.add("sink1", NodeKind::Sink);
217 let sources = reg.find_by_kind(&NodeKind::Source);
218 assert_eq!(sources.len(), 2);
219 }
220
221 #[test]
222 fn test_registry_enabled_count() {
223 let mut reg = NodeRegistry::new();
224 let id0 = reg.add("a", NodeKind::Source);
225 let id1 = reg.add("b", NodeKind::Filter);
226 reg.get_mut(id1)
227 .expect("get_mut should succeed")
228 .set_enabled(false);
229 assert_eq!(reg.enabled_count(), 1);
230 let _ = id0;
231 }
232
233 #[test]
234 fn test_registry_remove() {
235 let mut reg = NodeRegistry::new();
236 let id = reg.add("x", NodeKind::Mux);
237 assert!(reg.remove(id).is_some());
238 assert!(reg.is_empty());
239 }
240
241 #[test]
242 fn test_registry_len() {
243 let mut reg = NodeRegistry::new();
244 reg.add("a", NodeKind::Source);
245 reg.add("b", NodeKind::Sink);
246 assert_eq!(reg.len(), 2);
247 }
248
249 #[test]
250 fn test_registry_find_by_kind_empty() {
251 let reg = NodeRegistry::new();
252 assert!(reg.find_by_kind(&NodeKind::Mux).is_empty());
253 }
254
255 #[test]
256 fn test_registry_default() {
257 let reg: NodeRegistry = Default::default();
258 assert!(reg.is_empty());
259 }
260
261 #[test]
262 fn test_node_id_accessor() {
263 let n = GraphNode::new(42, "node42", NodeKind::Filter);
264 assert_eq!(n.id(), 42);
265 }
266}