use serde_json::Value;
use crate::{BoundaryKind, FindingKey, Polarity, Severity, ViolationId};
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct Violation {
pub kind: BoundaryKind,
pub target: String,
pub rule: String,
pub finding: String,
pub(crate) finding_key: FindingKey,
pub reason: String,
pub severity: Severity,
pub baselined: bool,
pub file: Option<String>,
pub anchor: Option<String>,
pub polarity: Option<Polarity>,
}
impl Violation {
pub fn new(kind: BoundaryKind, id: ViolationId, reason: String, severity: Severity) -> Self {
let ViolationId {
target,
rule,
finding,
finding_key,
} = id;
Violation {
kind,
target,
rule,
finding,
finding_key: finding_key.expect(
"a live violation requires a structured finding; a version-1 baseline id is legacy data, not an observed fact",
),
reason,
severity,
baselined: false,
file: None,
anchor: None,
polarity: None,
}
}
pub fn finding_key(&self) -> &FindingKey {
&self.finding_key
}
pub fn with_file(mut self, file: Option<String>) -> Self {
self.file = file;
self
}
pub fn with_anchor(mut self, anchor: Option<String>) -> Self {
self.anchor = anchor;
self
}
pub fn with_polarity(mut self, polarity: Polarity) -> Self {
self.polarity = Some(polarity);
self
}
pub fn id(&self) -> ViolationId {
ViolationId {
target: self.target.clone(),
rule: self.rule.clone(),
finding: self.finding.clone(),
finding_key: Some(self.finding_key.clone()),
}
}
pub fn to_json(&self) -> Value {
serde_json::json!({
"kind": self.kind.as_str(),
"target": self.target,
"rule": self.rule,
"finding": self.finding,
"finding_key": self.finding_key.to_json(),
"reason": self.reason,
"severity": self.severity.as_str(),
"baselined": self.baselined,
"file": self.file,
"anchor": self.anchor,
"polarity": self.polarity.map(|p| p.as_str()),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct Report {
pub violations: Vec<Violation>,
}
impl Report {
pub fn empty() -> Self {
Report {
violations: Vec::new(),
}
}
pub fn new(violations: Vec<Violation>) -> Self {
Report { violations }
}
}