1use clap::ValueEnum;
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7#[derive(
9 Debug, Clone, Copy, Default, PartialEq, Eq, ValueEnum, Serialize, Deserialize, JsonSchema,
10)]
11#[non_exhaustive]
12pub enum ReportFormat {
13 #[default]
15 Auto,
16 Tui,
18 #[value(alias = "side-by-side")]
20 SideBySide,
21 Json,
23 Sarif,
25 Markdown,
27 Html,
29 Summary,
31 Table,
33 Csv,
35 Ndjson,
37}
38
39impl std::fmt::Display for ReportFormat {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 match self {
42 Self::Auto => write!(f, "auto"),
43 Self::Tui => write!(f, "tui"),
44 Self::SideBySide => write!(f, "side-by-side"),
45 Self::Json => write!(f, "json"),
46 Self::Sarif => write!(f, "sarif"),
47 Self::Markdown => write!(f, "markdown"),
48 Self::Html => write!(f, "html"),
49 Self::Summary => write!(f, "summary"),
50 Self::Table => write!(f, "table"),
51 Self::Csv => write!(f, "csv"),
52 Self::Ndjson => write!(f, "ndjson"),
53 }
54 }
55}
56
57#[derive(
59 Debug, Clone, Copy, Default, PartialEq, Eq, ValueEnum, Serialize, Deserialize, JsonSchema,
60)]
61pub enum ReportType {
62 #[default]
64 All,
65 Components,
67 Dependencies,
69 Licenses,
71 Vulnerabilities,
73}
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
77pub enum MinSeverity {
78 Low,
79 Medium,
80 High,
81 Critical,
82}
83
84impl MinSeverity {
85 #[must_use]
87 pub fn parse(s: &str) -> Option<Self> {
88 match s.to_lowercase().as_str() {
89 "low" => Some(Self::Low),
90 "medium" => Some(Self::Medium),
91 "high" => Some(Self::High),
92 "critical" => Some(Self::Critical),
93 _ => None,
94 }
95 }
96
97 #[must_use]
99 pub fn meets_threshold(&self, severity: &str) -> bool {
100 let sev = match severity.to_lowercase().as_str() {
101 "critical" => Self::Critical,
102 "high" => Self::High,
103 "medium" => Self::Medium,
104 "low" => Self::Low,
105 _ => return true, };
107 sev >= *self
108 }
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct ReportConfig {
114 pub report_types: Vec<ReportType>,
116 pub include_unchanged: bool,
118 pub max_items: Option<usize>,
120 pub include_field_changes: bool,
122 pub title: Option<String>,
124 pub metadata: ReportMetadata,
126 pub only_changes: bool,
128 pub min_severity: Option<MinSeverity>,
130 #[serde(skip)]
132 pub old_cra_compliance: Option<crate::quality::ComplianceResult>,
133 #[serde(skip)]
135 pub new_cra_compliance: Option<crate::quality::ComplianceResult>,
136 #[serde(skip)]
138 pub view_cra_compliance: Option<crate::quality::ComplianceResult>,
139}
140
141impl Default for ReportConfig {
142 fn default() -> Self {
143 Self {
144 report_types: vec![ReportType::All],
145 include_unchanged: false,
146 max_items: None,
147 include_field_changes: true,
148 title: None,
149 metadata: ReportMetadata::default(),
150 only_changes: false,
151 min_severity: None,
152 old_cra_compliance: None,
153 new_cra_compliance: None,
154 view_cra_compliance: None,
155 }
156 }
157}
158
159impl ReportConfig {
160 #[must_use]
162 pub fn all() -> Self {
163 Self::default()
164 }
165
166 #[must_use]
168 pub fn with_types(types: Vec<ReportType>) -> Self {
169 Self {
170 report_types: types,
171 ..Default::default()
172 }
173 }
174
175 #[must_use]
177 pub fn includes(&self, report_type: ReportType) -> bool {
178 self.report_types.contains(&ReportType::All) || self.report_types.contains(&report_type)
179 }
180}
181
182#[derive(Debug, Clone, Default, Serialize, Deserialize)]
184pub struct ReportMetadata {
185 pub old_sbom_path: Option<String>,
187 pub new_sbom_path: Option<String>,
189 pub tool_version: String,
191 pub generated_at: Option<String>,
193 pub custom: std::collections::HashMap<String, String>,
195}
196
197impl ReportMetadata {
198 #[must_use]
199 pub fn new() -> Self {
200 Self {
201 tool_version: env!("CARGO_PKG_VERSION").to_string(),
202 ..Default::default()
203 }
204 }
205}