Skip to main content

sift_core/search/emit/
stats.rs

1use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
2use std::time::Duration;
3
4use grep_printer::Stats as JsonStats;
5
6#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
7pub struct SearchStats {
8    pub matches: usize,
9    pub files_with_matches: usize,
10    pub files_searched: usize,
11    pub bytes_printed: u64,
12    pub bytes_searched: u64,
13    pub elapsed: Duration,
14}
15
16impl SearchStats {
17    pub(crate) fn fill_from_json(
18        &mut self,
19        merged: &JsonStats,
20        candidates_len: usize,
21        bytes_searched_sum: u64,
22        elapsed: Duration,
23        summary_line_bytes: u64,
24    ) {
25        use std::convert::TryFrom;
26        self.matches = usize::try_from(merged.matches()).unwrap_or(usize::MAX);
27        self.files_with_matches =
28            usize::try_from(merged.searches_with_match()).unwrap_or(usize::MAX);
29        self.files_searched = candidates_len;
30        self.bytes_printed = merged.bytes_printed() + summary_line_bytes;
31        self.bytes_searched = bytes_searched_sum;
32        self.elapsed = elapsed;
33    }
34}
35
36#[derive(Debug)]
37pub struct TextStatsCounters {
38    primary: AtomicUsize,
39    files_with_matches: AtomicUsize,
40    bytes_printed: AtomicU64,
41    collect_stats: bool,
42}
43
44impl TextStatsCounters {
45    pub const fn new(collect_stats: bool) -> Self {
46        Self {
47            primary: AtomicUsize::new(0),
48            files_with_matches: AtomicUsize::new(0),
49            bytes_printed: AtomicU64::new(0),
50            collect_stats,
51        }
52    }
53
54    pub fn primary(&self) -> Option<&AtomicUsize> {
55        self.collect_stats.then_some(&self.primary)
56    }
57
58    pub fn files_with_matches(&self) -> Option<&AtomicUsize> {
59        self.collect_stats.then_some(&self.files_with_matches)
60    }
61
62    pub fn bytes_printed(&self) -> Option<&AtomicU64> {
63        self.collect_stats.then_some(&self.bytes_printed)
64    }
65
66    pub fn finish(
67        self,
68        candidates_len: usize,
69        bytes_searched: u64,
70        elapsed: Duration,
71    ) -> Option<SearchStats> {
72        if !self.collect_stats {
73            return None;
74        }
75        Some(SearchStats {
76            matches: self.primary.load(Ordering::Relaxed),
77            files_with_matches: self.files_with_matches.load(Ordering::Relaxed),
78            files_searched: candidates_len,
79            bytes_printed: self.bytes_printed.load(Ordering::Relaxed),
80            bytes_searched,
81            elapsed,
82        })
83    }
84}