use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[derive(Default)]
pub enum CycleKind {
#[default]
Calls,
Imports,
Modules,
}
impl CycleKind {
#[must_use]
pub const fn all() -> &'static [Self] {
&[Self::Calls, Self::Imports, Self::Modules]
}
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Calls => "calls",
Self::Imports => "imports",
Self::Modules => "modules",
}
}
#[must_use]
pub fn parse(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"calls" | "call" | "function" => Some(Self::Calls),
"imports" | "import" => Some(Self::Imports),
"modules" | "module" | "package" => Some(Self::Modules),
_ => None,
}
}
#[must_use]
pub const fn description(self) -> &'static str {
match self {
Self::Calls => "function/method call cycles",
Self::Imports => "import/dependency cycles",
Self::Modules => "module-level dependency cycles",
}
}
}
impl fmt::Display for CycleKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_as_str() {
assert_eq!(CycleKind::Calls.as_str(), "calls");
assert_eq!(CycleKind::Imports.as_str(), "imports");
assert_eq!(CycleKind::Modules.as_str(), "modules");
}
#[test]
fn test_parse() {
assert_eq!(CycleKind::parse("calls"), Some(CycleKind::Calls));
assert_eq!(CycleKind::parse("IMPORTS"), Some(CycleKind::Imports));
assert_eq!(CycleKind::parse("call"), Some(CycleKind::Calls));
assert_eq!(CycleKind::parse("package"), Some(CycleKind::Modules));
assert_eq!(CycleKind::parse("unknown"), None);
}
#[test]
fn test_display() {
assert_eq!(format!("{}", CycleKind::Calls), "calls");
assert_eq!(format!("{}", CycleKind::Modules), "modules");
}
#[test]
fn test_serde_roundtrip() {
for kind in CycleKind::all() {
let json = serde_json::to_string(kind).unwrap();
let deserialized: CycleKind = serde_json::from_str(&json).unwrap();
assert_eq!(*kind, deserialized);
}
}
#[test]
fn test_default() {
assert_eq!(CycleKind::default(), CycleKind::Calls);
}
#[test]
fn test_description() {
assert!(CycleKind::Calls.description().contains("call"));
assert!(CycleKind::Imports.description().contains("import"));
assert!(CycleKind::Modules.description().contains("module"));
}
}