Skip to main content

keyhog_core/
report.rs

1//! Reporting logic for scan results.
2
3mod csv;
4mod html;
5mod json;
6mod junit;
7mod sarif;
8mod text;
9
10#[path = "report/sarif_uri.rs"]
11pub mod sarif_uri;
12
13pub mod banner;
14
15use std::io::Write;
16
17use crate::VerifiedFinding;
18
19pub use csv::CsvReporter;
20pub use html::HtmlReporter;
21pub use json::{JsonArrayReporter, JsonReporter, JsonlReporter};
22pub use junit::JunitReporter;
23pub use sarif::SarifReporter;
24pub use text::TextReporter;
25
26/// Common error type used by all reporters.
27pub type ReportError = anyhow::Error;
28
29/// Common trait for all finding reporters.
30pub trait Reporter: Send {
31    /// Report a single finding.
32    fn report(&mut self, finding: &VerifiedFinding) -> Result<(), ReportError>;
33
34    /// Finalize the report and flush buffered bytes.
35    fn finish(&mut self) -> Result<(), ReportError>;
36}
37
38trait WriterBackedReporter {
39    type Writer: Write;
40
41    fn writer_mut(&mut self) -> &mut Self::Writer;
42
43    fn flush_writer(&mut self) -> Result<(), ReportError> {
44        self.writer_mut().flush()?;
45        Ok(())
46    }
47}
48
49// `BufferedFindingReporter` was the legacy buffer-everything trait. The
50// SARIF reporter now streams results directly to its writer (audit
51// legendary-2026-04-26), so the trait has no callers and is removed. Other
52// reporters that still buffer (text, JSON-array) keep their state inline.