count_zeroes/
lib.rs

1use std::io::BufRead;
2use std::io::Read;
3
4const DEFAULT_BUFFER_SIZE: usize = 64 * 1024;
5
6/// Count zeroes in something.
7pub trait CountZeroes<P> {
8    /// Count zeroes in `&mut self` and report `progress` at every iteration.
9    fn count_zeroes(&mut self, progress: P) -> Result<(u64, u64), std::io::Error>;
10}
11
12impl<R: Read, P: FnMut(u64, u64) -> bool> CountZeroes<P> for std::io::BufReader<R> {
13    fn count_zeroes(&mut self, mut progress: P) -> Result<(u64, u64), std::io::Error> {
14        let mut zeroes: u64 = 0;
15        let mut count: u64 = 0;
16
17        while let Ok(buffer) = self.fill_buf() {
18            let len = buffer.len();
19
20            if len == 0 {
21                break;
22            }
23
24            count += len as u64;
25            zeroes += buffer.iter().filter(|&&x| x == 0).count() as u64;
26
27            if !progress(zeroes, count) {
28                break;
29            }
30
31            self.consume(len);
32        }
33
34        Ok((zeroes, count))
35    }
36}
37
38impl<P: FnMut(u64, u64) -> bool> CountZeroes<P> for std::fs::File {
39    fn count_zeroes(&mut self, progress: P) -> Result<(u64, u64), std::io::Error> {
40        let mut reader = std::io::BufReader::with_capacity(DEFAULT_BUFFER_SIZE, self);
41
42        reader.count_zeroes(progress)
43    }
44}
45
46impl<R: Read> CountZeroes<()> for std::io::BufReader<R> {
47    fn count_zeroes(&mut self, _progress: ()) -> Result<(u64, u64), std::io::Error> {
48        self.count_zeroes(|_zeroes: u64, _count: u64| true)
49    }
50}
51
52impl CountZeroes<()> for std::fs::File {
53    fn count_zeroes(&mut self, progress: ()) -> Result<(u64, u64), std::io::Error> {
54        let mut reader = std::io::BufReader::with_capacity(DEFAULT_BUFFER_SIZE, self);
55
56        reader.count_zeroes(progress)
57    }
58}