1use clap::ValueEnum;
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, ValueEnum, Serialize, Deserialize, JsonSchema)]
9pub enum ReportFormat {
10 #[default]
12 Auto,
13 Tui,
15 #[value(alias = "side-by-side")]
17 SideBySide,
18 Json,
20 Sarif,
22 Markdown,
24 Html,
26 Summary,
28 Table,
30 Csv,
32}
33
34impl std::fmt::Display for ReportFormat {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 match self {
37 ReportFormat::Auto => write!(f, "auto"),
38 ReportFormat::Tui => write!(f, "tui"),
39 ReportFormat::SideBySide => write!(f, "side-by-side"),
40 ReportFormat::Json => write!(f, "json"),
41 ReportFormat::Sarif => write!(f, "sarif"),
42 ReportFormat::Markdown => write!(f, "markdown"),
43 ReportFormat::Html => write!(f, "html"),
44 ReportFormat::Summary => write!(f, "summary"),
45 ReportFormat::Table => write!(f, "table"),
46 ReportFormat::Csv => write!(f, "csv"),
47 }
48 }
49}
50
51#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, ValueEnum, Serialize, Deserialize, JsonSchema)]
53pub enum ReportType {
54 #[default]
56 All,
57 Components,
59 Dependencies,
61 OssDependencies,
63 Licenses,
65 Vulnerabilities,
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
71pub enum MinSeverity {
72 Low,
73 Medium,
74 High,
75 Critical,
76}
77
78impl MinSeverity {
79 pub fn parse(s: &str) -> Option<Self> {
81 match s.to_lowercase().as_str() {
82 "low" => Some(Self::Low),
83 "medium" => Some(Self::Medium),
84 "high" => Some(Self::High),
85 "critical" => Some(Self::Critical),
86 _ => None,
87 }
88 }
89
90 pub fn meets_threshold(&self, severity: &str) -> bool {
92 let sev = match severity.to_lowercase().as_str() {
93 "critical" => MinSeverity::Critical,
94 "high" => MinSeverity::High,
95 "medium" => MinSeverity::Medium,
96 "low" => MinSeverity::Low,
97 _ => return true, };
99 sev >= *self
100 }
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct ReportConfig {
106 pub report_types: Vec<ReportType>,
108 pub include_unchanged: bool,
110 pub max_items: Option<usize>,
112 pub include_field_changes: bool,
114 pub title: Option<String>,
116 pub metadata: ReportMetadata,
118 pub only_changes: bool,
120 pub min_severity: Option<MinSeverity>,
122 #[serde(skip)]
124 pub old_cra_compliance: Option<crate::quality::ComplianceResult>,
125 #[serde(skip)]
127 pub new_cra_compliance: Option<crate::quality::ComplianceResult>,
128 #[serde(skip)]
130 pub view_cra_compliance: Option<crate::quality::ComplianceResult>,
131}
132
133impl Default for ReportConfig {
134 fn default() -> Self {
135 Self {
136 report_types: vec![ReportType::All],
137 include_unchanged: false,
138 max_items: None,
139 include_field_changes: true,
140 title: None,
141 metadata: ReportMetadata::default(),
142 only_changes: false,
143 min_severity: None,
144 old_cra_compliance: None,
145 new_cra_compliance: None,
146 view_cra_compliance: None,
147 }
148 }
149}
150
151impl ReportConfig {
152 pub fn all() -> Self {
154 Self::default()
155 }
156
157 pub fn with_types(types: Vec<ReportType>) -> Self {
159 Self {
160 report_types: types,
161 ..Default::default()
162 }
163 }
164
165 pub fn includes(&self, report_type: ReportType) -> bool {
167 self.report_types.contains(&ReportType::All) || self.report_types.contains(&report_type)
168 }
169}
170
171#[derive(Debug, Clone, Default, Serialize, Deserialize)]
173pub struct ReportMetadata {
174 pub old_sbom_path: Option<String>,
176 pub new_sbom_path: Option<String>,
178 pub tool_version: String,
180 pub generated_at: Option<String>,
182 pub custom: std::collections::HashMap<String, String>,
184}
185
186impl ReportMetadata {
187 pub fn new() -> Self {
188 Self {
189 tool_version: env!("CARGO_PKG_VERSION").to_string(),
190 ..Default::default()
191 }
192 }
193}