#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NodeId(u64);
impl NodeId {
pub fn of<T: 'static>() -> Self {
let type_name = std::any::type_name::<T>();
Self::from_name(type_name)
}
pub fn from_name(name: &str) -> Self {
let hash = Self::hash_string(name);
Self(hash)
}
pub fn from_type_name(type_name: &str) -> Self {
Self::from_name(type_name)
}
pub fn as_u64(&self) -> u64 {
self.0
}
fn hash_string(s: &str) -> u64 {
let mut hash: u64 = 5381;
for byte in s.bytes() {
hash = hash.wrapping_mul(33).wrapping_add(u64::from(byte));
}
hash
}
}
impl std::fmt::Display for NodeId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "NodeId({})", self.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestType;
struct OtherType;
#[test]
fn test_node_id_of_same_type() {
let id1 = NodeId::of::<TestType>();
let id2 = NodeId::of::<TestType>();
assert_eq!(id1, id2);
}
#[test]
fn test_node_id_of_different_types() {
let id1 = NodeId::of::<TestType>();
let id2 = NodeId::of::<OtherType>();
assert_ne!(id1, id2);
}
#[test]
fn test_node_id_from_name() {
let id1 = NodeId::from_name("test");
let id2 = NodeId::from_name("test");
assert_eq!(id1, id2);
}
#[test]
fn test_node_id_from_different_names() {
let id1 = NodeId::from_name("test1");
let id2 = NodeId::from_name("test2");
assert_ne!(id1, id2);
}
#[test]
fn test_node_id_as_u64() {
let id = NodeId::from_name("test");
let value = id.as_u64();
assert!(value > 0);
}
#[test]
fn test_node_id_display() {
let id = NodeId::from_name("test");
let display = format!("{}", id);
assert!(display.starts_with("NodeId("));
}
}