use std::collections::BTreeMap;
use std::path::Path;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct TomlConfig {
pub scan: ScanConfig,
pub module: ModuleConfig,
pub export: ExportConfig,
pub analyze: AnalyzeConfig,
pub context: ContextConfig,
pub badge: BadgeConfig,
pub gate: GateConfig,
#[serde(default)]
pub view: BTreeMap<String, ViewProfile>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct ScanConfig {
pub paths: Option<Vec<String>>,
pub exclude: Option<Vec<String>>,
pub hidden: Option<bool>,
pub config: Option<String>,
pub no_ignore: Option<bool>,
pub no_ignore_parent: Option<bool>,
pub no_ignore_dot: Option<bool>,
pub no_ignore_vcs: Option<bool>,
pub doc_comments: Option<bool>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct ModuleConfig {
pub roots: Option<Vec<String>>,
pub depth: Option<usize>,
pub children: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct ExportConfig {
pub min_code: Option<usize>,
pub max_rows: Option<usize>,
pub redact: Option<String>,
pub format: Option<String>,
pub children: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct AnalyzeConfig {
pub preset: Option<String>,
pub window: Option<usize>,
pub format: Option<String>,
pub git: Option<bool>,
pub max_files: Option<usize>,
pub max_bytes: Option<u64>,
pub max_file_bytes: Option<u64>,
pub max_commits: Option<usize>,
pub max_commit_files: Option<usize>,
pub granularity: Option<String>,
pub effort_model: Option<String>,
pub effort_layer: Option<String>,
pub effort_base_ref: Option<String>,
pub effort_head_ref: Option<String>,
pub effort_monte_carlo: Option<bool>,
pub effort_mc_iterations: Option<usize>,
pub effort_mc_seed: Option<u64>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct ContextConfig {
pub budget: Option<String>,
pub strategy: Option<String>,
pub rank_by: Option<String>,
pub output: Option<String>,
pub compress: Option<bool>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct BadgeConfig {
pub metric: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct GateConfig {
pub policy: Option<String>,
pub baseline: Option<String>,
pub preset: Option<String>,
pub fail_fast: Option<bool>,
pub rules: Option<Vec<GateRule>>,
pub ratchet: Option<Vec<RatchetRuleConfig>>,
pub allow_missing_baseline: Option<bool>,
pub allow_missing_current: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RatchetRuleConfig {
pub pointer: String,
#[serde(default)]
pub max_increase_pct: Option<f64>,
#[serde(default)]
pub max_value: Option<f64>,
#[serde(default)]
pub level: Option<String>,
#[serde(default)]
pub description: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GateRule {
pub name: String,
pub pointer: String,
pub op: String,
#[serde(default)]
pub value: Option<serde_json::Value>,
#[serde(default)]
pub values: Option<Vec<serde_json::Value>>,
#[serde(default)]
pub negate: bool,
#[serde(default)]
pub level: Option<String>,
#[serde(default)]
pub message: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct ViewProfile {
pub format: Option<String>,
pub top: Option<usize>,
pub files: Option<bool>,
pub module_roots: Option<Vec<String>>,
pub module_depth: Option<usize>,
pub min_code: Option<usize>,
pub max_rows: Option<usize>,
pub redact: Option<String>,
pub meta: Option<bool>,
pub children: Option<String>,
pub preset: Option<String>,
pub window: Option<usize>,
pub budget: Option<String>,
pub strategy: Option<String>,
pub rank_by: Option<String>,
pub output: Option<String>,
pub compress: Option<bool>,
pub metric: Option<String>,
}
impl TomlConfig {
pub fn parse(s: &str) -> Result<Self, toml::de::Error> {
toml::from_str(s)
}
pub fn from_file(path: &Path) -> std::io::Result<Self> {
let content = std::fs::read_to_string(path)?;
toml::from_str(&content)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
}
}