1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize)]
20#[non_exhaustive]
21pub enum EdgeKind {
22 Ownership,
24
25 Import,
27
28 Reference,
30}
31
32impl EdgeKind {
33 pub fn participates_in_scc(self) -> bool {
35 matches!(self, EdgeKind::Import | EdgeKind::Reference)
36 }
37
38 pub fn is_cross_file(self) -> bool {
40 matches!(self, EdgeKind::Import)
41 }
42
43 pub const fn as_str(self) -> &'static str {
45 match self {
46 EdgeKind::Ownership => "ownership",
47 EdgeKind::Import => "import",
48 EdgeKind::Reference => "reference",
49 }
50 }
51}
52
53impl std::fmt::Display for EdgeKind {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 write!(f, "{}", self.as_str())
56 }
57}
58
59#[derive(Debug, Clone, Copy, serde::Serialize)]
61pub struct EdgeData {
62 pub kind: EdgeKind,
64
65 pub confidence: f32,
68}
69
70impl EdgeData {
71 pub fn new(kind: EdgeKind) -> Self {
73 Self {
74 kind,
75 confidence: 1.0,
76 }
77 }
78
79 pub fn with_confidence(kind: EdgeKind, confidence: f32) -> Self {
81 Self {
82 kind,
83 confidence: confidence.clamp(0.0, 1.0),
84 }
85 }
86 pub fn participates_in_scc(&self) -> bool {
87 self.kind.participates_in_scc()
88 }
89}
90
91impl Default for EdgeData {
92 fn default() -> Self {
93 Self::new(EdgeKind::Reference)
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn edge_kind_scc_participation() {
103 assert!(!EdgeKind::Ownership.participates_in_scc());
104 assert!(EdgeKind::Import.participates_in_scc());
105 assert!(EdgeKind::Reference.participates_in_scc());
106 }
107
108 #[test]
109 fn edge_kind_as_str() {
110 assert_eq!(EdgeKind::Ownership.as_str(), "ownership");
111 assert_eq!(EdgeKind::Import.as_str(), "import");
112 assert_eq!(EdgeKind::Reference.as_str(), "reference");
113 }
114
115 #[test]
116 fn edge_kind_display() {
117 assert_eq!(format!("{}", EdgeKind::Import), "import");
118 }
119
120 #[test]
121 fn edge_data_new_defaults_to_full_confidence() {
122 let edge = EdgeData::new(EdgeKind::Import);
123 assert_eq!(edge.kind, EdgeKind::Import);
124 assert_eq!(edge.confidence, 1.0);
125 assert!(edge.participates_in_scc());
126 }
127
128 #[test]
129 fn edge_data_with_confidence_clamps() {
130 let low = EdgeData::with_confidence(EdgeKind::Reference, -0.5);
131 assert_eq!(low.confidence, 0.0);
132
133 let high = EdgeData::with_confidence(EdgeKind::Reference, 1.5);
134 assert_eq!(high.confidence, 1.0);
135
136 let mid = EdgeData::with_confidence(EdgeKind::Reference, 0.75);
137 assert_eq!(mid.confidence, 0.75);
138 }
139
140 #[test]
141 fn edge_data_default() {
142 let edge: EdgeData = Default::default();
143 assert_eq!(edge.confidence, 1.0);
144 assert!(edge.participates_in_scc());
145 }
146}