vf3/
types.rs

1//! Domain-specific types for graph operations.
2//!
3//! This module provides newtype wrappers that enforce type safety
4//! and make the API more expressive.
5
6use std::fmt;
7
8/// A node identifier in a graph.
9///
10/// This newtype wrapper ensures type safety when working with node indices.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct NodeId(pub usize);
13
14impl NodeId {
15    /// Creates a new node identifier.
16    #[inline]
17    pub fn new(id: usize) -> Self {
18        NodeId(id)
19    }
20
21    /// Returns the underlying index value.
22    #[inline]
23    pub fn index(&self) -> usize {
24        self.0
25    }
26
27    /// Converts to usize for internal use.
28    #[inline]
29    #[allow(dead_code)] // Reserved for future internal use
30    pub(crate) fn as_usize(&self) -> usize {
31        self.0
32    }
33}
34
35impl fmt::Display for NodeId {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        write!(f, "Node({})", self.0)
38    }
39}
40
41impl From<usize> for NodeId {
42    #[inline]
43    fn from(id: usize) -> Self {
44        NodeId(id)
45    }
46}
47
48impl From<NodeId> for usize {
49    #[inline]
50    fn from(id: NodeId) -> Self {
51        id.0
52    }
53}
54
55/// A label attached to a node.
56///
57/// Labels are used to match nodes with identical properties
58/// during subgraph isomorphism detection.
59#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
60pub struct NodeLabel(pub u32);
61
62impl NodeLabel {
63    /// Creates a new node label.
64    #[inline]
65    pub fn new(label: u32) -> Self {
66        NodeLabel(label)
67    }
68
69    /// Returns the underlying label value.
70    #[inline]
71    pub fn value(&self) -> u32 {
72        self.0
73    }
74
75    /// Default label for unlabeled nodes.
76    pub const DEFAULT: Self = NodeLabel(0);
77}
78
79impl Default for NodeLabel {
80    #[inline]
81    fn default() -> Self {
82        Self::DEFAULT
83    }
84}
85
86impl fmt::Display for NodeLabel {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        write!(f, "L{}", self.0)
89    }
90}
91
92impl From<u32> for NodeLabel {
93    #[inline]
94    fn from(label: u32) -> Self {
95        NodeLabel(label)
96    }
97}
98
99impl From<NodeLabel> for u32 {
100    #[inline]
101    fn from(label: NodeLabel) -> Self {
102        label.0
103    }
104}
105
106/// A label attached to an edge.
107///
108/// Edge labels are used to match edges with identical properties
109/// during subgraph isomorphism detection.
110#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
111pub struct EdgeLabel(pub u32);
112
113impl EdgeLabel {
114    /// Creates a new edge label.
115    #[inline]
116    pub fn new(label: u32) -> Self {
117        EdgeLabel(label)
118    }
119
120    /// Returns the underlying label value.
121    #[inline]
122    pub fn value(&self) -> u32 {
123        self.0
124    }
125
126    /// Default label for unlabeled edges.
127    pub const DEFAULT: Self = EdgeLabel(0);
128}
129
130impl Default for EdgeLabel {
131    #[inline]
132    fn default() -> Self {
133        Self::DEFAULT
134    }
135}
136
137impl fmt::Display for EdgeLabel {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        write!(f, "E{}", self.0)
140    }
141}
142
143impl From<u32> for EdgeLabel {
144    #[inline]
145    fn from(label: u32) -> Self {
146        EdgeLabel(label)
147    }
148}
149
150impl From<EdgeLabel> for u32 {
151    #[inline]
152    fn from(label: EdgeLabel) -> Self {
153        label.0
154    }
155}
156
157/// Represents a mapping between nodes in the pattern and target graphs.
158///
159/// Each tuple represents a (pattern_node, target_node) pair.
160/// For backwards compatibility, we use raw usize internally.
161pub type NodeMapping = Vec<(usize, usize)>;
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166
167    #[test]
168    fn test_node_id_creation() {
169        let id = NodeId::new(42);
170        assert_eq!(id.index(), 42);
171        assert_eq!(id.as_usize(), 42);
172    }
173
174    #[test]
175    fn test_node_label_default() {
176        let label = NodeLabel::default();
177        assert_eq!(label.value(), 0);
178        assert_eq!(label, NodeLabel::DEFAULT);
179    }
180
181    #[test]
182    fn test_edge_label_conversion() {
183        let label = EdgeLabel::from(10);
184        assert_eq!(label.value(), 10);
185        let value: u32 = label.into();
186        assert_eq!(value, 10);
187    }
188
189    #[test]
190    fn test_display_formatting() {
191        assert_eq!(format!("{}", NodeId::new(5)), "Node(5)");
192        assert_eq!(format!("{}", NodeLabel::new(3)), "L3");
193        assert_eq!(format!("{}", EdgeLabel::new(7)), "E7");
194    }
195}