#![allow(dead_code)]
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum NodeKind {
Source,
Filter,
Sink,
Mux,
}
impl NodeKind {
pub fn is_source(&self) -> bool {
*self == NodeKind::Source
}
pub fn is_sink(&self) -> bool {
*self == NodeKind::Sink
}
pub fn label(&self) -> &'static str {
match self {
NodeKind::Source => "source",
NodeKind::Filter => "filter",
NodeKind::Sink => "sink",
NodeKind::Mux => "mux",
}
}
}
#[derive(Debug, Clone)]
pub struct GraphNode {
id: u64,
name: String,
kind: NodeKind,
enabled: bool,
}
impl GraphNode {
pub fn new(id: u64, name: impl Into<String>, kind: NodeKind) -> Self {
Self {
id,
name: name.into(),
kind,
enabled: true,
}
}
pub fn id(&self) -> u64 {
self.id
}
pub fn name(&self) -> &str {
&self.name
}
pub fn kind(&self) -> &NodeKind {
&self.kind
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
}
#[derive(Debug, Clone, Default)]
pub struct NodeRegistry {
nodes: HashMap<u64, GraphNode>,
next_id: u64,
}
impl NodeRegistry {
pub fn new() -> Self {
Self {
nodes: HashMap::new(),
next_id: 0,
}
}
pub fn add(&mut self, name: impl Into<String>, kind: NodeKind) -> u64 {
let id = self.next_id;
self.next_id += 1;
self.nodes.insert(id, GraphNode::new(id, name, kind));
id
}
pub fn get(&self, id: u64) -> Option<&GraphNode> {
self.nodes.get(&id)
}
pub fn get_mut(&mut self, id: u64) -> Option<&mut GraphNode> {
self.nodes.get_mut(&id)
}
pub fn find_by_kind(&self, kind: &NodeKind) -> Vec<&GraphNode> {
self.nodes.values().filter(|n| n.kind() == kind).collect()
}
pub fn enabled_count(&self) -> usize {
self.nodes.values().filter(|n| n.is_enabled()).count()
}
pub fn len(&self) -> usize {
self.nodes.len()
}
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
pub fn remove(&mut self, id: u64) -> Option<GraphNode> {
self.nodes.remove(&id)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_node_kind_is_source() {
assert!(NodeKind::Source.is_source());
assert!(!NodeKind::Sink.is_source());
}
#[test]
fn test_node_kind_is_sink() {
assert!(NodeKind::Sink.is_sink());
assert!(!NodeKind::Filter.is_sink());
}
#[test]
fn test_node_kind_label() {
assert_eq!(NodeKind::Source.label(), "source");
assert_eq!(NodeKind::Filter.label(), "filter");
assert_eq!(NodeKind::Sink.label(), "sink");
assert_eq!(NodeKind::Mux.label(), "mux");
}
#[test]
fn test_graph_node_enabled_by_default() {
let n = GraphNode::new(0, "node0", NodeKind::Source);
assert!(n.is_enabled());
}
#[test]
fn test_graph_node_set_enabled() {
let mut n = GraphNode::new(0, "node0", NodeKind::Filter);
n.set_enabled(false);
assert!(!n.is_enabled());
}
#[test]
fn test_registry_add_returns_incremental_ids() {
let mut reg = NodeRegistry::new();
let id0 = reg.add("a", NodeKind::Source);
let id1 = reg.add("b", NodeKind::Sink);
assert_eq!(id0, 0);
assert_eq!(id1, 1);
}
#[test]
fn test_registry_get() {
let mut reg = NodeRegistry::new();
let id = reg.add("scaler", NodeKind::Filter);
let node = reg.get(id).expect("get should succeed");
assert_eq!(node.name(), "scaler");
assert_eq!(node.kind(), &NodeKind::Filter);
}
#[test]
fn test_registry_find_by_kind() {
let mut reg = NodeRegistry::new();
reg.add("src1", NodeKind::Source);
reg.add("src2", NodeKind::Source);
reg.add("sink1", NodeKind::Sink);
let sources = reg.find_by_kind(&NodeKind::Source);
assert_eq!(sources.len(), 2);
}
#[test]
fn test_registry_enabled_count() {
let mut reg = NodeRegistry::new();
let id0 = reg.add("a", NodeKind::Source);
let id1 = reg.add("b", NodeKind::Filter);
reg.get_mut(id1)
.expect("get_mut should succeed")
.set_enabled(false);
assert_eq!(reg.enabled_count(), 1);
let _ = id0;
}
#[test]
fn test_registry_remove() {
let mut reg = NodeRegistry::new();
let id = reg.add("x", NodeKind::Mux);
assert!(reg.remove(id).is_some());
assert!(reg.is_empty());
}
#[test]
fn test_registry_len() {
let mut reg = NodeRegistry::new();
reg.add("a", NodeKind::Source);
reg.add("b", NodeKind::Sink);
assert_eq!(reg.len(), 2);
}
#[test]
fn test_registry_find_by_kind_empty() {
let reg = NodeRegistry::new();
assert!(reg.find_by_kind(&NodeKind::Mux).is_empty());
}
#[test]
fn test_registry_default() {
let reg: NodeRegistry = Default::default();
assert!(reg.is_empty());
}
#[test]
fn test_node_id_accessor() {
let n = GraphNode::new(42, "node42", NodeKind::Filter);
assert_eq!(n.id(), 42);
}
}