#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum CircularType {
Calls,
Imports,
Modules,
}
impl CircularType {
#[must_use]
pub fn try_parse(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"calls" | "call" => Some(Self::Calls),
"imports" | "import" => Some(Self::Imports),
"modules" | "module" => Some(Self::Modules),
_ => None,
}
}
}
#[derive(Debug, Clone)]
pub struct CircularConfig {
pub min_depth: usize,
pub max_depth: Option<usize>,
pub max_results: usize,
pub should_include_self_loops: bool,
}
impl Default for CircularConfig {
fn default() -> Self {
Self {
min_depth: 2,
max_depth: None,
max_results: 100,
should_include_self_loops: false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_canonical_plural_forms() {
assert_eq!(CircularType::try_parse("calls"), Some(CircularType::Calls));
assert_eq!(
CircularType::try_parse("imports"),
Some(CircularType::Imports)
);
assert_eq!(
CircularType::try_parse("modules"),
Some(CircularType::Modules)
);
}
#[test]
fn parses_legacy_singular_aliases() {
assert_eq!(CircularType::try_parse("call"), Some(CircularType::Calls));
assert_eq!(
CircularType::try_parse("import"),
Some(CircularType::Imports)
);
assert_eq!(
CircularType::try_parse("module"),
Some(CircularType::Modules)
);
}
#[test]
fn is_case_insensitive() {
assert_eq!(CircularType::try_parse("CALLS"), Some(CircularType::Calls));
assert_eq!(
CircularType::try_parse("Imports"),
Some(CircularType::Imports)
);
}
#[test]
fn rejects_unknown_types() {
assert_eq!(CircularType::try_parse("unknown"), None);
assert_eq!(CircularType::try_parse(""), None);
}
#[test]
fn default_config_matches_legacy() {
let config = CircularConfig::default();
assert_eq!(config.min_depth, 2);
assert_eq!(config.max_depth, None);
assert_eq!(config.max_results, 100);
assert!(!config.should_include_self_loops);
}
}