use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum Severity {
Critical,
#[default]
Warning,
Info,
}
impl std::fmt::Display for Severity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Severity::Critical => "critical",
Severity::Warning => "warning",
Severity::Info => "info",
};
f.pad(s)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RuleInfo {
pub id: String,
pub severity: Severity,
pub description: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Finding {
pub rule_id: String,
pub severity: Severity,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub file: Option<String>,
pub location: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct AuditSummary {
pub critical: usize,
pub warning: usize,
pub info: usize,
pub total: usize,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct AuditReport {
pub findings: Vec<Finding>,
pub summary: AuditSummary,
}
impl AuditReport {
pub fn add(&mut self, f: Finding) {
match f.severity {
Severity::Critical => self.summary.critical += 1,
Severity::Warning => self.summary.warning += 1,
Severity::Info => self.summary.info += 1,
}
self.summary.total += 1;
self.findings.push(f);
}
pub fn is_clean(&self) -> bool {
self.findings.is_empty()
}
}