use crate::format::RuleCategory;
#[derive(Debug, Clone)]
pub struct ParsedRule {
pub source: Option<std::path::PathBuf>,
pub line: Option<usize>,
pub rule: UnifiedRule,
}
#[derive(Debug, Clone)]
pub struct WorkflowStepData {
pub name: String,
pub description: String,
pub condition: Option<String>,
pub actions: Vec<String>,
}
#[derive(Debug, Clone)]
pub enum UnifiedRule {
Persona {
name: String,
role: String,
identity: Option<String>,
style: Option<String>,
traits: Vec<String>,
principles: Vec<String>,
},
Standard {
category: RuleCategory,
priority: u8,
description: String,
pattern: Option<String>,
},
Context {
includes: Vec<String>,
excludes: Vec<String>,
focus: Vec<String>,
},
Workflow {
name: String,
steps: Vec<WorkflowStepData>,
},
Raw {
content: String,
},
}
impl UnifiedRule {
pub fn persona(name: impl Into<String>, role: impl Into<String>) -> Self {
Self::Persona {
name: name.into(),
role: role.into(),
identity: None,
style: None,
traits: Vec::new(),
principles: Vec::new(),
}
}
pub fn standard(category: RuleCategory, priority: u8, description: impl Into<String>) -> Self {
Self::Standard {
category,
priority,
description: description.into(),
pattern: None,
}
}
pub fn context(includes: Vec<String>, excludes: Vec<String>) -> Self {
Self::Context {
includes,
excludes,
focus: Vec::new(),
}
}
pub fn workflow(name: impl Into<String>, steps: Vec<WorkflowStepData>) -> Self {
Self::Workflow {
name: name.into(),
steps,
}
}
pub fn raw(content: impl Into<String>) -> Self {
Self::Raw {
content: content.into(),
}
}
pub fn type_name(&self) -> &'static str {
match self {
UnifiedRule::Persona { .. } => "persona",
UnifiedRule::Standard { .. } => "standard",
UnifiedRule::Context { .. } => "context",
UnifiedRule::Workflow { .. } => "workflow",
UnifiedRule::Raw { .. } => "raw",
}
}
}
impl std::fmt::Display for UnifiedRule {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UnifiedRule::Persona { name, role, .. } => {
write!(f, "Persona[{}]: {}", name, role)
}
UnifiedRule::Standard {
category,
description,
..
} => {
write!(f, "Standard[{:?}]: {}", category, description)
}
UnifiedRule::Context { includes, .. } => {
write!(f, "Context: {} patterns", includes.len())
}
UnifiedRule::Workflow { name, steps } => {
write!(f, "Workflow[{}]: {} steps", name, steps.len())
}
UnifiedRule::Raw { content } => {
let preview: String = content.chars().take(50).collect();
write!(f, "Raw: {}...", preview)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_persona_creation() {
let rule = UnifiedRule::persona("Architect", "Senior system architect");
assert_eq!(rule.type_name(), "persona");
if let UnifiedRule::Persona { name, role, .. } = rule {
assert_eq!(name, "Architect");
assert_eq!(role, "Senior system architect");
} else {
panic!("Expected Persona variant");
}
}
#[test]
fn test_standard_creation() {
let rule = UnifiedRule::standard(RuleCategory::Naming, 1, "Use snake_case for functions");
assert_eq!(rule.type_name(), "standard");
}
#[test]
fn test_display() {
let rule = UnifiedRule::persona("Test", "Tester");
let display = format!("{}", rule);
assert!(display.contains("Persona"));
assert!(display.contains("Test"));
}
}