Skip to main content

sift_core/search/emit/
result.rs

1use std::io::{self, Write};
2use std::sync::atomic::{AtomicU64, Ordering};
3
4pub struct FileResult {
5    pub output: ChunkOutput,
6    pub json_stats: Option<grep_printer::Stats>,
7    pub hit: Option<std::path::PathBuf>,
8}
9
10pub struct ChunkOutput {
11    pub bytes: Vec<u8>,
12    pub matched: bool,
13    pub heading: bool,
14}
15
16impl ChunkOutput {
17    #[must_use]
18    pub const fn empty() -> Self {
19        Self {
20            bytes: Vec::new(),
21            matched: false,
22            heading: false,
23        }
24    }
25
26    /// # Errors
27    ///
28    /// Returns an error if writing to stdout fails.
29    pub fn flush_all(
30        outputs: impl IntoIterator<Item = Self>,
31        bytes_printed: Option<&AtomicU64>,
32    ) -> crate::Result<bool> {
33        let mut stdout = io::stdout().lock();
34        let mut any_match = false;
35        let mut emitted = false;
36        for output in outputs {
37            any_match |= output.matched;
38            if output.bytes.is_empty() {
39                continue;
40            }
41            if output.heading && emitted {
42                stdout.write_all(b"\n")?;
43                if let Some(p) = bytes_printed {
44                    p.fetch_add(1, Ordering::Relaxed);
45                }
46            }
47            let n = output.bytes.len() as u64;
48            if let Some(p) = bytes_printed {
49                p.fetch_add(n, Ordering::Relaxed);
50            }
51            stdout.write_all(&output.bytes)?;
52            emitted = true;
53        }
54        Ok(any_match)
55    }
56}