1use std::fmt;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum Severity {
5 Fatal,
6 Warning,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct Finding {
11 pub id: &'static str,
12 pub severity: Severity,
13 pub message: String,
14}
15
16impl Finding {
17 pub fn fatal(id: &'static str, message: impl Into<String>) -> Self {
18 Self {
19 id,
20 severity: Severity::Fatal,
21 message: message.into(),
22 }
23 }
24}
25
26#[derive(Debug, Clone, Default, PartialEq, Eq)]
27pub struct Report {
28 pub findings: Vec<Finding>,
29}
30
31impl Report {
32 pub fn ok(&self) -> bool {
33 !self
34 .findings
35 .iter()
36 .any(|f| f.severity == Severity::Fatal)
37 }
38
39 pub fn push(&mut self, finding: Finding) {
40 self.findings.push(finding);
41 }
42}
43
44impl fmt::Display for Report {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 if self.ok() {
47 return write!(f, "valid");
48 }
49 for finding in &self.findings {
50 writeln!(f, "[{}] {}", finding.id, finding.message)?;
51 }
52 Ok(())
53 }
54}