Skip to main content

keyhog_core/report/
json.rs

1//! Machine-readable JSON reporters: JSON Lines for streams and pretty JSON arrays
2//! for batch output.
3
4use std::io::Write;
5
6use crate::VerifiedFinding;
7
8use super::{ReportError, Reporter, WriterBackedReporter};
9
10/// One JSON object per line (JSONL).
11///
12/// # Examples
13///
14/// ```rust
15/// use keyhog_core::JsonlReporter;
16///
17/// let reporter = JsonlReporter::new(Vec::new());
18/// let _ = reporter;
19/// ```
20pub struct JsonlReporter<W: Write + Send> {
21    writer: W,
22}
23
24impl<W: Write + Send> JsonlReporter<W> {
25    /// Create a JSON Lines reporter.
26    ///
27    /// # Examples
28    ///
29    /// ```rust
30    /// use keyhog_core::JsonlReporter;
31    ///
32    /// let reporter = JsonlReporter::new(Vec::new());
33    /// let _ = reporter;
34    /// ```
35    pub fn new(writer: W) -> Self {
36        Self { writer }
37    }
38}
39
40impl<W: Write + Send> Reporter for JsonlReporter<W> {
41    fn report(&mut self, finding: &VerifiedFinding) -> Result<(), ReportError> {
42        serde_json::to_writer(&mut self.writer, finding)?;
43        writeln!(self.writer)?;
44        Ok(())
45    }
46
47    fn finish(&mut self) -> Result<(), ReportError> {
48        self.flush_writer()
49    }
50}
51
52impl<W: Write + Send> WriterBackedReporter for JsonlReporter<W> {
53    type Writer = W;
54
55    fn writer_mut(&mut self) -> &mut Self::Writer {
56        &mut self.writer
57    }
58}
59
60/// Full JSON array output.
61///
62/// # Examples
63///
64/// ```rust
65/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
66/// use keyhog_core::JsonArrayReporter;
67///
68/// let reporter = JsonArrayReporter::new(Vec::new())?;
69/// let _ = reporter;
70/// # Ok(()) }
71/// ```
72pub struct JsonArrayReporter<W: Write + Send> {
73    writer: W,
74    first: bool,
75}
76
77impl<W: Write + Send> JsonArrayReporter<W> {
78    /// Create a JSON array reporter.
79    ///
80    /// # Examples
81    ///
82    /// ```rust
83    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
84    /// use keyhog_core::JsonArrayReporter;
85    ///
86    /// let reporter = JsonArrayReporter::new(Vec::new())?;
87    /// let _ = reporter;
88    /// # Ok(()) }
89    /// ```
90    pub fn new(mut writer: W) -> Result<Self, ReportError> {
91        write!(writer, "[")?;
92        Ok(Self {
93            writer,
94            first: true,
95        })
96    }
97}
98
99impl<W: Write + Send> Reporter for JsonArrayReporter<W> {
100    fn report(&mut self, finding: &VerifiedFinding) -> Result<(), ReportError> {
101        if !self.first {
102            write!(self.writer, ",")?;
103        }
104        serde_json::to_writer(&mut self.writer, finding)?;
105        self.first = false;
106        Ok(())
107    }
108
109    fn finish(&mut self) -> Result<(), ReportError> {
110        write!(self.writer, "]")?;
111        self.flush_writer()
112    }
113}
114
115impl<W: Write + Send> WriterBackedReporter for JsonArrayReporter<W> {
116    type Writer = W;
117
118    fn writer_mut(&mut self) -> &mut Self::Writer {
119        &mut self.writer
120    }
121}
122
123/// Alias for [`JsonArrayReporter`] for standard JSON output.
124pub type JsonReporter<W> = JsonArrayReporter<W>;