1use serde::{Deserialize, Serialize};
4
5use crate::id::NodeId;
6use crate::kind::EdgeKind;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15pub struct Edge {
16 from: NodeId,
17 to: NodeId,
18 kind: EdgeKind,
19 #[serde(default, skip_serializing_if = "Option::is_none")]
20 label: Option<String>,
21}
22
23impl Edge {
24 pub fn new(from: NodeId, to: NodeId, kind: EdgeKind) -> Self {
26 Self {
27 from,
28 to,
29 kind,
30 label: None,
31 }
32 }
33
34 pub fn with_label(from: NodeId, to: NodeId, kind: EdgeKind, label: &str) -> Self {
36 Self {
37 from,
38 to,
39 kind,
40 label: Some(label.to_owned()),
41 }
42 }
43
44 pub fn from_id(&self) -> &NodeId {
46 &self.from
47 }
48
49 pub fn to_id(&self) -> &NodeId {
51 &self.to
52 }
53
54 pub fn kind(&self) -> EdgeKind {
56 self.kind
57 }
58
59 pub fn label(&self) -> Option<&str> {
61 self.label.as_deref()
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn test_new() {
71 let edge = Edge::new(
72 NodeId::new("a").unwrap(),
73 NodeId::new("b").unwrap(),
74 EdgeKind::Uses,
75 );
76 assert_eq!(edge.from_id().as_str(), "a");
77 assert_eq!(edge.to_id().as_str(), "b");
78 assert_eq!(edge.kind(), EdgeKind::Uses);
79 assert_eq!(edge.label(), None);
80 }
81
82 #[test]
83 fn test_with_label() {
84 let edge = Edge::with_label(
85 NodeId::new("api").unwrap(),
86 NodeId::new("db").unwrap(),
87 EdgeKind::Reads,
88 "SQL queries",
89 );
90 assert_eq!(edge.label(), Some("SQL queries"));
91 }
92
93 #[test]
94 fn test_serde_round_trip() {
95 let edge = Edge::with_label(
96 NodeId::new("api").unwrap(),
97 NodeId::new("db").unwrap(),
98 EdgeKind::Writes,
99 "inserts",
100 );
101 let json = serde_json::to_string(&edge).unwrap();
102 let deserialized: Edge = serde_json::from_str(&json).unwrap();
103 assert_eq!(edge, deserialized);
104 }
105
106 #[test]
107 fn test_serde_omits_none_label() {
108 let edge = Edge::new(
109 NodeId::new("a").unwrap(),
110 NodeId::new("b").unwrap(),
111 EdgeKind::Uses,
112 );
113 let json = serde_json::to_string(&edge).unwrap();
114 assert!(!json.contains("label"));
115 }
116}