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}
36
37impl std::fmt::Display for ReportFormat {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 match self {
40 Self::Auto => write!(f, "auto"),
41 Self::Tui => write!(f, "tui"),
42 Self::SideBySide => write!(f, "side-by-side"),
43 Self::Json => write!(f, "json"),
44 Self::Sarif => write!(f, "sarif"),
45 Self::Markdown => write!(f, "markdown"),
46 Self::Html => write!(f, "html"),
47 Self::Summary => write!(f, "summary"),
48 Self::Table => write!(f, "table"),
49 Self::Csv => write!(f, "csv"),
50 }
51 }
52}
53
54#[derive(
56 Debug, Clone, Copy, Default, PartialEq, Eq, ValueEnum, Serialize, Deserialize, JsonSchema,
57)]
58pub enum ReportType {
59 #[default]
61 All,
62 Components,
64 Dependencies,
66 OssDependencies,
68 Licenses,
70 Vulnerabilities,
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
76pub enum MinSeverity {
77 Low,
78 Medium,
79 High,
80 Critical,
81}
82
83impl MinSeverity {
84 #[must_use]
86 pub fn parse(s: &str) -> Option<Self> {
87 match s.to_lowercase().as_str() {
88 "low" => Some(Self::Low),
89 "medium" => Some(Self::Medium),
90 "high" => Some(Self::High),
91 "critical" => Some(Self::Critical),
92 _ => None,
93 }
94 }
95
96 #[must_use]
98 pub fn meets_threshold(&self, severity: &str) -> bool {
99 let sev = match severity.to_lowercase().as_str() {
100 "critical" => Self::Critical,
101 "high" => Self::High,
102 "medium" => Self::Medium,
103 "low" => Self::Low,
104 _ => return true, };
106 sev >= *self
107 }
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct ReportConfig {
113 pub report_types: Vec<ReportType>,
115 pub include_unchanged: bool,
117 pub max_items: Option<usize>,
119 pub include_field_changes: bool,
121 pub title: Option<String>,
123 pub metadata: ReportMetadata,
125 pub only_changes: bool,
127 pub min_severity: Option<MinSeverity>,
129 #[serde(skip)]
131 pub old_cra_compliance: Option<crate::quality::ComplianceResult>,
132 #[serde(skip)]
134 pub new_cra_compliance: Option<crate::quality::ComplianceResult>,
135 #[serde(skip)]
137 pub view_cra_compliance: Option<crate::quality::ComplianceResult>,
138}
139
140impl Default for ReportConfig {
141 fn default() -> Self {
142 Self {
143 report_types: vec![ReportType::All],
144 include_unchanged: false,
145 max_items: None,
146 include_field_changes: true,
147 title: None,
148 metadata: ReportMetadata::default(),
149 only_changes: false,
150 min_severity: None,
151 old_cra_compliance: None,
152 new_cra_compliance: None,
153 view_cra_compliance: None,
154 }
155 }
156}
157
158impl ReportConfig {
159 #[must_use]
161 pub fn all() -> Self {
162 Self::default()
163 }
164
165 #[must_use]
167 pub fn with_types(types: Vec<ReportType>) -> Self {
168 Self {
169 report_types: types,
170 ..Default::default()
171 }
172 }
173
174 #[must_use]
176 pub fn includes(&self, report_type: ReportType) -> bool {
177 self.report_types.contains(&ReportType::All) || self.report_types.contains(&report_type)
178 }
179}
180
181#[derive(Debug, Clone, Default, Serialize, Deserialize)]
183pub struct ReportMetadata {
184 pub old_sbom_path: Option<String>,
186 pub new_sbom_path: Option<String>,
188 pub tool_version: String,
190 pub generated_at: Option<String>,
192 pub custom: std::collections::HashMap<String, String>,
194}
195
196impl ReportMetadata {
197 #[must_use]
198 pub fn new() -> Self {
199 Self {
200 tool_version: env!("CARGO_PKG_VERSION").to_string(),
201 ..Default::default()
202 }
203 }
204}