use std::collections::HashMap;
pub type NodeId = usize;
#[derive(Debug)]
pub enum NodeError {
GenericError(String),
}
impl std::fmt::Display for NodeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
NodeError::GenericError(msg) => write!(f, "Node error: {}", msg),
}
}
}
impl std::error::Error for NodeError {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Node<W, N> {
pub data: N,
pub neighbors: Vec<(NodeId, W)>,
pub attributes: HashMap<String, String>,
}
impl<W, N: Default> Default for Node<W, N> {
fn default() -> Self {
Self {
data: N::default(),
neighbors: Vec::new(),
attributes: HashMap::new(),
}
}
}
impl<W, N> Node<W, N> {
pub fn new(data: N) -> Self {
Node {
data,
neighbors: Vec::new(),
attributes: HashMap::new(),
}
}
pub fn add_neighbor(&mut self, neighbor_id: NodeId, weight: W) {
self.neighbors.push((neighbor_id, weight));
}
pub fn get_attribute(&self, key: &str) -> Option<&String> {
self.attributes.get(key)
}
pub fn set_attribute(&mut self, key: String, value: String) -> Result<(), NodeError> {
self.attributes.insert(key, value);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_node_creation() {
let node = Node::<i32, &str>::new("Test");
assert_eq!(node.data, "Test");
assert!(node.neighbors.is_empty());
assert!(node.attributes.is_empty());
}
#[test]
fn test_default_node() {
let node: Node<f64, String> = Node::default();
assert_eq!(node.data, String::new());
assert!(node.neighbors.is_empty());
assert!(node.attributes.is_empty());
}
#[test]
fn test_add_neighbor() {
let mut node = Node::<u32, i32>::new(1);
node.add_neighbor(2, 10);
node.add_neighbor(3, 20);
assert_eq!(node.neighbors, vec![(2, 10), (3, 20)]);
}
#[test]
fn test_attributes() {
let mut node = Node::<f32, &str>::new("Node");
node.set_attribute("size".to_string(), "large".to_string())
.unwrap();
assert_eq!(node.get_attribute("size"), Some(&"large".to_string()));
assert_eq!(node.get_attribute("color"), None);
}
}