1use std::sync::atomic::{AtomicU32, Ordering};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
5pub struct NodeId(u32);
6
7impl NodeId {
8 pub const fn from_raw(id: u32) -> Self {
14 NodeId(id)
15 }
16
17 pub const fn as_raw(&self) -> u32 {
19 self.0
20 }
21}
22
23impl std::fmt::Display for NodeId {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 write!(f, "NodeId({})", self.0)
26 }
27}
28
29pub struct NodeIdGenerator {
46 next_id: AtomicU32,
47}
48
49impl NodeIdGenerator {
50 pub const fn new() -> Self {
52 Self { next_id: AtomicU32::new(1) }
53 }
54
55 pub fn next(&self) -> NodeId {
61 let id = self.next_id.fetch_add(1, Ordering::SeqCst);
62 assert!(id < u32::MAX, "NodeId counter overflow");
63 NodeId(id)
64 }
65
66 #[cfg(test)]
68 pub fn reset(&self) {
69 self.next_id.store(1, Ordering::SeqCst);
70 }
71}
72
73impl Default for NodeIdGenerator {
74 fn default() -> Self {
75 Self::new()
76 }
77}
78
79static GLOBAL_GENERATOR: NodeIdGenerator = NodeIdGenerator::new();
83
84pub fn new_node_id() -> NodeId {
88 GLOBAL_GENERATOR.next()
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_node_id_basic() {
97 let id1 = NodeId::from_raw(42);
98 let id2 = NodeId::from_raw(42);
99 assert_eq!(id1, id2);
100 assert_eq!(id1.as_raw(), 42);
101 }
102
103 #[test]
104 fn test_node_id_display() {
105 let id = NodeId::from_raw(123);
106 assert_eq!(format!("{}", id), "NodeId(123)");
107 }
108
109 #[test]
110 fn test_node_id_ordering() {
111 let id1 = NodeId::from_raw(10);
112 let id2 = NodeId::from_raw(20);
113 assert!(id1 < id2);
114 assert!(id2 > id1);
115 }
116
117 #[test]
118 fn test_node_id_generator() {
119 let gen = NodeIdGenerator::new();
120 let id1 = gen.next();
121 let id2 = gen.next();
122 assert_ne!(id1, id2);
123 assert_eq!(id1.as_raw() + 1, id2.as_raw());
124 }
125
126 #[test]
127 fn test_global_generator_thread_safe() {
128 use std::sync::Arc;
129 use std::thread;
130
131 let ids = Arc::new(std::sync::Mutex::new(Vec::new()));
132 let mut handles = vec![];
133
134 for _ in 0..10 {
136 let ids_clone = Arc::clone(&ids);
137 let handle = thread::spawn(move || {
138 for _ in 0..100 {
139 let id = new_node_id();
140 ids_clone.lock().unwrap().push(id);
141 }
142 });
143 handles.push(handle);
144 }
145
146 for handle in handles {
147 handle.join().unwrap();
148 }
149
150 let mut id_set = std::collections::HashSet::new();
152 for id in ids.lock().unwrap().iter() {
153 assert!(id_set.insert(*id), "Duplicate NodeId generated");
154 }
155 assert_eq!(id_set.len(), 1000);
156 }
157}