Skip to main content

axiolid_model/
id.rs

1//! Typed graph identity.
2
3use core::fmt;
4use core::sync::atomic::{AtomicU64, Ordering};
5
6static NEXT_GRAPH_ID: AtomicU64 = AtomicU64::new(1);
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub(crate) struct GraphId(u64);
10
11impl GraphId {
12    pub(crate) fn fresh() -> Self {
13        let value = NEXT_GRAPH_ID
14            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current| {
15                current.checked_add(1)
16            })
17            .expect("geometry graph identity space exhausted");
18        Self(value)
19    }
20}
21
22/// Stable index owned by one immutable [`crate::GeometryGraph`].
23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
24pub struct NodeId {
25    graph: GraphId,
26    index: u32,
27}
28
29impl NodeId {
30    pub(crate) fn from_index(graph: GraphId, index: usize) -> Self {
31        Self {
32            graph,
33            index: u32::try_from(index).expect("geometry graph exceeds u32 capacity"),
34        }
35    }
36
37    pub(crate) fn belongs_to(self, graph: GraphId) -> bool {
38        self.graph == graph
39    }
40
41    /// Zero-based graph index.
42    pub const fn index(self) -> usize {
43        self.index as usize
44    }
45}
46
47impl fmt::Display for NodeId {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        write!(f, "geometry#{}", self.index)
50    }
51}