ringkernel_graph/models/
node.rs1use bytemuck::{Pod, Zeroable};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, PartialOrd, Ord)]
14#[repr(transparent)]
15pub struct NodeId(pub u32);
16
17impl NodeId {
18 pub const MAX: NodeId = NodeId(u32::MAX - 1);
20
21 pub const INVALID: NodeId = NodeId(u32::MAX);
23
24 pub const fn new(id: u32) -> Self {
26 NodeId(id)
27 }
28
29 pub const fn is_valid(&self) -> bool {
31 self.0 != u32::MAX
32 }
33
34 pub const fn get(&self) -> u32 {
36 self.0
37 }
38}
39
40impl From<u32> for NodeId {
41 fn from(id: u32) -> Self {
42 NodeId(id)
43 }
44}
45
46impl From<usize> for NodeId {
47 fn from(id: usize) -> Self {
48 NodeId(id as u32)
49 }
50}
51
52impl From<NodeId> for usize {
53 fn from(id: NodeId) -> Self {
54 id.0 as usize
55 }
56}
57
58unsafe impl Zeroable for NodeId {}
60unsafe impl Pod for NodeId {}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, PartialOrd, Ord)]
66#[repr(transparent)]
67pub struct Distance(pub u32);
68
69impl Distance {
70 pub const INFINITY: Distance = Distance(u32::MAX);
72
73 pub const ZERO: Distance = Distance(0);
75
76 pub const fn new(d: u32) -> Self {
78 Distance(d)
79 }
80
81 pub const fn is_reachable(&self) -> bool {
83 self.0 != u32::MAX
84 }
85
86 pub const fn get(&self) -> u32 {
88 self.0
89 }
90
91 pub const fn increment(&self) -> Self {
93 if self.0 == u32::MAX {
94 Distance::INFINITY
95 } else {
96 Distance(self.0.saturating_add(1))
97 }
98 }
99}
100
101impl From<u32> for Distance {
102 fn from(d: u32) -> Self {
103 Distance(d)
104 }
105}
106
107unsafe impl Zeroable for Distance {}
109unsafe impl Pod for Distance {}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, PartialOrd, Ord)]
115#[repr(transparent)]
116pub struct ComponentId(pub u32);
117
118impl ComponentId {
119 pub const UNASSIGNED: ComponentId = ComponentId(u32::MAX);
121
122 pub const fn new(id: u32) -> Self {
124 ComponentId(id)
125 }
126
127 pub const fn is_assigned(&self) -> bool {
129 self.0 != u32::MAX
130 }
131
132 pub const fn get(&self) -> u32 {
134 self.0
135 }
136}
137
138impl From<u32> for ComponentId {
139 fn from(id: u32) -> Self {
140 ComponentId(id)
141 }
142}
143
144impl From<NodeId> for ComponentId {
145 fn from(id: NodeId) -> Self {
146 ComponentId(id.0)
147 }
148}
149
150unsafe impl Zeroable for ComponentId {}
152unsafe impl Pod for ComponentId {}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
159 fn test_node_id_basics() {
160 let node = NodeId::new(42);
161 assert_eq!(node.get(), 42);
162 assert!(node.is_valid());
163 assert!(!NodeId::INVALID.is_valid());
164 }
165
166 #[test]
167 fn test_node_id_conversions() {
168 let node: NodeId = 100u32.into();
169 assert_eq!(node.get(), 100);
170
171 let idx: usize = node.into();
172 assert_eq!(idx, 100);
173 }
174
175 #[test]
176 fn test_distance_basics() {
177 let d = Distance::new(5);
178 assert_eq!(d.get(), 5);
179 assert!(d.is_reachable());
180 assert!(!Distance::INFINITY.is_reachable());
181 }
182
183 #[test]
184 fn test_distance_increment() {
185 let d = Distance::new(5);
186 assert_eq!(d.increment().get(), 6);
187
188 assert_eq!(Distance::INFINITY.increment(), Distance::INFINITY);
190 }
191
192 #[test]
193 fn test_component_id_basics() {
194 let c = ComponentId::new(3);
195 assert_eq!(c.get(), 3);
196 assert!(c.is_assigned());
197 assert!(!ComponentId::UNASSIGNED.is_assigned());
198 }
199
200 #[test]
201 fn test_pod_traits() {
202 let nodes = [NodeId::new(0), NodeId::new(1), NodeId::new(2)];
204 let bytes = bytemuck::bytes_of(&nodes);
205 assert_eq!(bytes.len(), 12); let distances = [Distance::ZERO, Distance::new(1), Distance::INFINITY];
208 let bytes = bytemuck::bytes_of(&distances);
209 assert_eq!(bytes.len(), 12);
210 }
211}