sqry_core/schema/
relation.rs1use serde::{Deserialize, Serialize};
6use std::fmt;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
29#[serde(rename_all = "lowercase")]
30#[derive(Default)]
31pub enum RelationKind {
32 #[default]
36 Callers,
37
38 Callees,
42
43 Imports,
47
48 Exports,
52
53 Returns,
57
58 Wraps,
66
67 #[serde(rename = "channel_peers")]
76 ChannelPeers,
77
78 #[serde(rename = "instantiations")]
85 Instantiations,
86}
87
88impl RelationKind {
89 #[must_use]
91 pub const fn all() -> &'static [Self] {
92 &[
93 Self::Callers,
94 Self::Callees,
95 Self::Imports,
96 Self::Exports,
97 Self::Returns,
98 Self::Wraps,
99 Self::ChannelPeers,
100 Self::Instantiations,
101 ]
102 }
103
104 #[must_use]
106 pub const fn as_str(self) -> &'static str {
107 match self {
108 Self::Callers => "callers",
109 Self::Callees => "callees",
110 Self::Imports => "imports",
111 Self::Exports => "exports",
112 Self::Returns => "returns",
113 Self::Wraps => "wraps",
114 Self::ChannelPeers => "channel_peers",
115 Self::Instantiations => "instantiations",
116 }
117 }
118
119 #[must_use]
124 pub fn parse(s: &str) -> Option<Self> {
125 match s.to_lowercase().as_str() {
126 "callers" => Some(Self::Callers),
127 "callees" => Some(Self::Callees),
128 "imports" => Some(Self::Imports),
129 "exports" => Some(Self::Exports),
130 "returns" => Some(Self::Returns),
131 "wraps" => Some(Self::Wraps),
132 "channel_peers" => Some(Self::ChannelPeers),
133 "instantiations" => Some(Self::Instantiations),
134 _ => None,
135 }
136 }
137
138 #[must_use]
140 pub const fn is_call_relation(self) -> bool {
141 matches!(self, Self::Callers | Self::Callees)
142 }
143
144 #[must_use]
146 pub const fn is_boundary_relation(self) -> bool {
147 matches!(self, Self::Imports | Self::Exports)
148 }
149}
150
151impl fmt::Display for RelationKind {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 f.write_str(self.as_str())
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160
161 #[test]
162 fn test_as_str() {
163 assert_eq!(RelationKind::Callers.as_str(), "callers");
164 assert_eq!(RelationKind::Callees.as_str(), "callees");
165 assert_eq!(RelationKind::Imports.as_str(), "imports");
166 assert_eq!(RelationKind::Exports.as_str(), "exports");
167 assert_eq!(RelationKind::Returns.as_str(), "returns");
168 }
169
170 #[test]
171 fn test_parse() {
172 assert_eq!(RelationKind::parse("callers"), Some(RelationKind::Callers));
173 assert_eq!(RelationKind::parse("CALLEES"), Some(RelationKind::Callees));
174 assert_eq!(RelationKind::parse("Imports"), Some(RelationKind::Imports));
175 assert_eq!(RelationKind::parse("unknown"), None);
176 }
177
178 #[test]
179 fn test_new_relation_kinds_wire_strings() {
180 assert_eq!(RelationKind::ChannelPeers.as_str(), "channel_peers");
183 assert_eq!(RelationKind::Instantiations.as_str(), "instantiations");
184 assert_eq!(
185 RelationKind::parse("channel_peers"),
186 Some(RelationKind::ChannelPeers)
187 );
188 assert_eq!(
189 RelationKind::parse("instantiations"),
190 Some(RelationKind::Instantiations)
191 );
192 assert_eq!(
194 serde_json::to_string(&RelationKind::ChannelPeers).unwrap(),
195 "\"channel_peers\""
196 );
197 assert_eq!(
198 serde_json::to_string(&RelationKind::Instantiations).unwrap(),
199 "\"instantiations\""
200 );
201 assert!(!RelationKind::ChannelPeers.is_call_relation());
203 assert!(!RelationKind::Instantiations.is_boundary_relation());
204 }
205
206 #[test]
207 fn test_display() {
208 assert_eq!(format!("{}", RelationKind::Callers), "callers");
209 assert_eq!(format!("{}", RelationKind::Returns), "returns");
210 }
211
212 #[test]
213 fn test_serde_roundtrip() {
214 for kind in RelationKind::all() {
215 let json = serde_json::to_string(kind).unwrap();
216 let deserialized: RelationKind = serde_json::from_str(&json).unwrap();
217 assert_eq!(*kind, deserialized);
218 }
219 }
220
221 #[test]
222 fn test_classification() {
223 assert!(RelationKind::Callers.is_call_relation());
224 assert!(RelationKind::Callees.is_call_relation());
225 assert!(!RelationKind::Imports.is_call_relation());
226
227 assert!(RelationKind::Imports.is_boundary_relation());
228 assert!(RelationKind::Exports.is_boundary_relation());
229 assert!(!RelationKind::Callers.is_boundary_relation());
230 }
231}