1use std::io::BufRead;
2use std::io::Read;
3
4const DEFAULT_BUFFER_SIZE: usize = 64 * 1024;
5
6pub trait CountZeroes<P> {
8 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}