Skip to main content

rsigma_runtime/io/
file.rs

1use std::fs::{File, OpenOptions};
2use std::io::{BufWriter, Write};
3use std::path::Path;
4
5use rsigma_eval::ProcessResult;
6
7use crate::error::RuntimeError;
8
9/// Appends ProcessResult as NDJSON to a file with buffered writes.
10pub struct FileSink {
11    writer: BufWriter<File>,
12}
13
14impl FileSink {
15    /// Open (or create) the file at `path` for appending.
16    pub fn open(path: &Path) -> Result<Self, RuntimeError> {
17        let file = OpenOptions::new().create(true).append(true).open(path)?;
18        Ok(FileSink {
19            writer: BufWriter::new(file),
20        })
21    }
22
23    /// Serialize and append a ProcessResult to the file.
24    pub fn send(&mut self, result: &ProcessResult) -> Result<(), RuntimeError> {
25        if result.detections.is_empty() && result.correlations.is_empty() {
26            return Ok(());
27        }
28
29        for m in &result.detections {
30            let json = serde_json::to_string(m)?;
31            writeln!(self.writer, "{json}")?;
32        }
33
34        for m in &result.correlations {
35            let json = serde_json::to_string(m)?;
36            writeln!(self.writer, "{json}")?;
37        }
38
39        self.writer.flush()?;
40        Ok(())
41    }
42
43    /// Write a pre-serialized JSON string directly to the file.
44    pub fn send_raw(&mut self, json: &str) -> Result<(), RuntimeError> {
45        writeln!(self.writer, "{json}")?;
46        self.writer.flush()?;
47        Ok(())
48    }
49}