sqry_core/schema/
cycle.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 CycleKind {
32 #[default]
37 Calls,
38
39 Imports,
44
45 Modules,
50}
51
52impl CycleKind {
53 #[must_use]
55 pub const fn all() -> &'static [Self] {
56 &[Self::Calls, Self::Imports, Self::Modules]
57 }
58
59 #[must_use]
61 pub const fn as_str(self) -> &'static str {
62 match self {
63 Self::Calls => "calls",
64 Self::Imports => "imports",
65 Self::Modules => "modules",
66 }
67 }
68
69 #[must_use]
74 pub fn parse(s: &str) -> Option<Self> {
75 match s.to_lowercase().as_str() {
76 "calls" | "call" | "function" => Some(Self::Calls),
77 "imports" | "import" => Some(Self::Imports),
78 "modules" | "module" | "package" => Some(Self::Modules),
79 _ => None,
80 }
81 }
82
83 #[must_use]
85 pub const fn description(self) -> &'static str {
86 match self {
87 Self::Calls => "function/method call cycles",
88 Self::Imports => "import/dependency cycles",
89 Self::Modules => "module-level dependency cycles",
90 }
91 }
92}
93
94impl fmt::Display for CycleKind {
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 f.write_str(self.as_str())
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_as_str() {
106 assert_eq!(CycleKind::Calls.as_str(), "calls");
107 assert_eq!(CycleKind::Imports.as_str(), "imports");
108 assert_eq!(CycleKind::Modules.as_str(), "modules");
109 }
110
111 #[test]
112 fn test_parse() {
113 assert_eq!(CycleKind::parse("calls"), Some(CycleKind::Calls));
114 assert_eq!(CycleKind::parse("IMPORTS"), Some(CycleKind::Imports));
115 assert_eq!(CycleKind::parse("call"), Some(CycleKind::Calls));
116 assert_eq!(CycleKind::parse("package"), Some(CycleKind::Modules));
117 assert_eq!(CycleKind::parse("unknown"), None);
118 }
119
120 #[test]
121 fn test_display() {
122 assert_eq!(format!("{}", CycleKind::Calls), "calls");
123 assert_eq!(format!("{}", CycleKind::Modules), "modules");
124 }
125
126 #[test]
127 fn test_serde_roundtrip() {
128 for kind in CycleKind::all() {
129 let json = serde_json::to_string(kind).unwrap();
130 let deserialized: CycleKind = serde_json::from_str(&json).unwrap();
131 assert_eq!(*kind, deserialized);
132 }
133 }
134
135 #[test]
136 fn test_default() {
137 assert_eq!(CycleKind::default(), CycleKind::Calls);
138 }
139
140 #[test]
141 fn test_description() {
142 assert!(CycleKind::Calls.description().contains("call"));
143 assert!(CycleKind::Imports.description().contains("import"));
144 assert!(CycleKind::Modules.description().contains("module"));
145 }
146}