oxgraph_hyper_bcsr/id.rs
1//! Local identifier newtypes and role enum for bipartite-CSR hypergraph
2//! views.
3
4use core::fmt;
5
6/// Side of a directed hyperedge an incidence belongs to.
7///
8/// `oxgraph-hyper` keeps the participation role as an associated type rather
9/// than a concrete enum so views can pick whatever vocabulary fits their
10/// storage. `BcsrRole` is the role chosen for [`BcsrHypergraph`](crate::BcsrHypergraph):
11/// each participant is either on the head side or the tail side of a directed
12/// hyperedge. Role bytes are not stored — the role is recovered from which
13/// section the participant lives in.
14///
15/// # Performance
16///
17/// Copying, comparing, ordering, hashing, and debug-formatting are `O(1)`.
18#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
19pub enum BcsrRole {
20 /// The vertex participates on the source (head) side of a directed hyperedge.
21 Head,
22 /// The vertex participates on the target (tail) side of a directed hyperedge.
23 Tail,
24}
25
26/// Local vertex ID for [`BcsrHypergraph`](crate::BcsrHypergraph).
27///
28/// Values are dense handles in `0..vertex_count` for one validated
29/// view. They are layout-local IDs and are not stable across rebuilding or
30/// compaction unless a higher layer defines that contract.
31///
32/// # Performance
33///
34/// Copying, comparing, ordering, hashing, and debug-formatting are `O(1)`.
35#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
36pub struct BcsrVertexId<VertexIndex>(pub VertexIndex);
37
38impl<VertexIndex> fmt::Debug for BcsrVertexId<VertexIndex>
39where
40 VertexIndex: fmt::Debug,
41{
42 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
43 formatter
44 .debug_tuple("BcsrVertexId")
45 .field(&self.0)
46 .finish()
47 }
48}
49
50impl<VertexIndex> From<VertexIndex> for BcsrVertexId<VertexIndex> {
51 fn from(value: VertexIndex) -> Self {
52 Self(value)
53 }
54}
55
56/// Local hyperedge ID for [`BcsrHypergraph`](crate::BcsrHypergraph).
57///
58/// Values are dense handles in `0..hyperedge_count` for one validated
59/// view. They are layout-local IDs and are not stable across rebuilding or
60/// compaction unless a higher layer defines that contract.
61///
62/// # Performance
63///
64/// Copying, comparing, ordering, hashing, and debug-formatting are `O(1)`.
65#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
66pub struct BcsrHyperedgeId<RelationIndex>(pub RelationIndex);
67
68impl<RelationIndex> fmt::Debug for BcsrHyperedgeId<RelationIndex>
69where
70 RelationIndex: fmt::Debug,
71{
72 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
73 formatter
74 .debug_tuple("BcsrHyperedgeId")
75 .field(&self.0)
76 .finish()
77 }
78}
79
80impl<RelationIndex> From<RelationIndex> for BcsrHyperedgeId<RelationIndex> {
81 fn from(value: RelationIndex) -> Self {
82 Self(value)
83 }
84}
85
86/// Local participant (incidence) ID for [`BcsrHypergraph`](crate::BcsrHypergraph).
87///
88/// Participant IDs span a single dense `u32` index space anchored on the
89/// hyperedge-major arrays:
90///
91/// - `[0, P_head)` are head incidences; the value indexes `head_participants`.
92/// - `[P_head, P_head + P_tail)` are tail incidences; subtracting `P_head` yields a position in
93/// `tail_participants`.
94///
95/// They are layout-local IDs and are not stable across rebuilding or
96/// compaction unless a higher layer defines that contract.
97///
98/// # Performance
99///
100/// Copying, comparing, ordering, hashing, and debug-formatting are `O(1)`.
101#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
102pub struct BcsrParticipantId<IncidenceIndex>(pub IncidenceIndex);
103
104impl<IncidenceIndex> fmt::Debug for BcsrParticipantId<IncidenceIndex>
105where
106 IncidenceIndex: fmt::Debug,
107{
108 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
109 formatter
110 .debug_tuple("BcsrParticipantId")
111 .field(&self.0)
112 .finish()
113 }
114}