grep_printer/
stats.rs

1use std::{
2    ops::{Add, AddAssign},
3    time::Duration,
4};
5
6use crate::util::NiceDuration;
7
8/// Summary statistics produced at the end of a search.
9///
10/// When statistics are reported by a printer, they correspond to all searches
11/// executed with that printer.
12#[derive(Clone, Debug, Default, PartialEq, Eq)]
13pub struct Stats {
14    elapsed: NiceDuration,
15    searches: u64,
16    searches_with_match: u64,
17    bytes_searched: u64,
18    bytes_printed: u64,
19    matched_lines: u64,
20    matches: u64,
21}
22
23impl Stats {
24    /// Return a new value for tracking aggregate statistics across searches.
25    ///
26    /// All statistics are set to `0`.
27    pub fn new() -> Stats {
28        Stats::default()
29    }
30
31    /// Return the total amount of time elapsed.
32    pub fn elapsed(&self) -> Duration {
33        self.elapsed.0
34    }
35
36    /// Return the total number of searches executed.
37    pub fn searches(&self) -> u64 {
38        self.searches
39    }
40
41    /// Return the total number of searches that found at least one match.
42    pub fn searches_with_match(&self) -> u64 {
43        self.searches_with_match
44    }
45
46    /// Return the total number of bytes searched.
47    pub fn bytes_searched(&self) -> u64 {
48        self.bytes_searched
49    }
50
51    /// Return the total number of bytes printed.
52    pub fn bytes_printed(&self) -> u64 {
53        self.bytes_printed
54    }
55
56    /// Return the total number of lines that participated in a match.
57    ///
58    /// When matches may contain multiple lines then this includes every line
59    /// that is part of every match.
60    pub fn matched_lines(&self) -> u64 {
61        self.matched_lines
62    }
63
64    /// Return the total number of matches.
65    ///
66    /// There may be multiple matches per line.
67    pub fn matches(&self) -> u64 {
68        self.matches
69    }
70
71    /// Add to the elapsed time.
72    pub fn add_elapsed(&mut self, duration: Duration) {
73        self.elapsed.0 += duration;
74    }
75
76    /// Add to the number of searches executed.
77    pub fn add_searches(&mut self, n: u64) {
78        self.searches += n;
79    }
80
81    /// Add to the number of searches that found at least one match.
82    pub fn add_searches_with_match(&mut self, n: u64) {
83        self.searches_with_match += n;
84    }
85
86    /// Add to the total number of bytes searched.
87    pub fn add_bytes_searched(&mut self, n: u64) {
88        self.bytes_searched += n;
89    }
90
91    /// Add to the total number of bytes printed.
92    pub fn add_bytes_printed(&mut self, n: u64) {
93        self.bytes_printed += n;
94    }
95
96    /// Add to the total number of lines that participated in a match.
97    pub fn add_matched_lines(&mut self, n: u64) {
98        self.matched_lines += n;
99    }
100
101    /// Add to the total number of matches.
102    pub fn add_matches(&mut self, n: u64) {
103        self.matches += n;
104    }
105}
106
107impl Add for Stats {
108    type Output = Stats;
109
110    fn add(self, rhs: Stats) -> Stats {
111        self + &rhs
112    }
113}
114
115impl<'a> Add<&'a Stats> for Stats {
116    type Output = Stats;
117
118    fn add(self, rhs: &'a Stats) -> Stats {
119        Stats {
120            elapsed: NiceDuration(self.elapsed.0 + rhs.elapsed.0),
121            searches: self.searches + rhs.searches,
122            searches_with_match: self.searches_with_match
123                + rhs.searches_with_match,
124            bytes_searched: self.bytes_searched + rhs.bytes_searched,
125            bytes_printed: self.bytes_printed + rhs.bytes_printed,
126            matched_lines: self.matched_lines + rhs.matched_lines,
127            matches: self.matches + rhs.matches,
128        }
129    }
130}
131
132impl AddAssign for Stats {
133    fn add_assign(&mut self, rhs: Stats) {
134        *self += &rhs;
135    }
136}
137
138impl<'a> AddAssign<&'a Stats> for Stats {
139    fn add_assign(&mut self, rhs: &'a Stats) {
140        self.elapsed.0 += rhs.elapsed.0;
141        self.searches += rhs.searches;
142        self.searches_with_match += rhs.searches_with_match;
143        self.bytes_searched += rhs.bytes_searched;
144        self.bytes_printed += rhs.bytes_printed;
145        self.matched_lines += rhs.matched_lines;
146        self.matches += rhs.matches;
147    }
148}
149
150#[cfg(feature = "serde")]
151impl serde::Serialize for Stats {
152    fn serialize<S: serde::Serializer>(
153        &self,
154        s: S,
155    ) -> Result<S::Ok, S::Error> {
156        use serde::ser::SerializeStruct;
157
158        let mut state = s.serialize_struct("Stats", 7)?;
159        state.serialize_field("elapsed", &self.elapsed)?;
160        state.serialize_field("searches", &self.searches)?;
161        state.serialize_field(
162            "searches_with_match",
163            &self.searches_with_match,
164        )?;
165        state.serialize_field("bytes_searched", &self.bytes_searched)?;
166        state.serialize_field("bytes_printed", &self.bytes_printed)?;
167        state.serialize_field("matched_lines", &self.matched_lines)?;
168        state.serialize_field("matches", &self.matches)?;
169        state.end()
170    }
171}