1use digest::{Digest, FixedOutputReset, Output, Reset};
2use std::io;
3
4#[derive(Debug)]
6pub struct HashReader<D: Digest, R: io::Read> {
7 reader: R,
8 hasher: D,
9}
10
11impl<D: Digest, R: io::Read> HashReader<D, R> {
12 pub fn new(reader: R) -> Self {
14 Self::new_from_parts(D::new(), reader)
15 }
16
17 pub fn new_from_parts(hasher: D, reader: R) -> Self {
19 HashReader { reader, hasher }
20 }
21
22 pub fn replace_reader(&mut self, reader: R) {
24 self.reader = reader;
25 }
26
27 pub fn get_hasher(&self) -> &D {
29 &self.hasher
30 }
31
32 pub fn get_reader(&self) -> &R {
34 &self.reader
35 }
36
37 pub fn get_hasher_mut(&mut self) -> &mut D {
39 &mut self.hasher
40 }
41
42 pub fn get_reader_mut(&mut self) -> &mut R {
45 &mut self.reader
46 }
47
48 pub fn into_hasher(self) -> D {
50 self.hasher
51 }
52
53 pub fn into_inner_reader(self) -> R {
55 self.reader
56 }
57
58 pub fn into_parts(self) -> (D, R) {
60 (self.hasher, self.reader)
61 }
62
63 pub fn finalize(self) -> Output<D> {
65 self.hasher.finalize()
66 }
67
68 pub fn finalize_into(self, out: &mut Output<D>) {
70 self.hasher.finalize_into(out)
71 }
72
73 pub fn output_size() -> usize {
75 <D as Digest>::output_size()
76 }
77}
78
79impl<D: Digest + Clone, R: io::Read + Clone> Clone for HashReader<D, R> {
80 fn clone(&self) -> HashReader<D, R> {
81 HashReader {
82 reader: self.reader.clone(),
83 hasher: self.hasher.clone(),
84 }
85 }
86}
87
88impl<D: Digest, R: io::Read> io::Read for HashReader<D, R> {
89 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
90 let bytes = self.reader.read(buf)?;
91
92 if bytes > 0 {
93 self.hasher.update(&buf[0..bytes]);
94 }
95
96 Ok(bytes)
97 }
98}
99
100impl<D: Digest + FixedOutputReset, R: io::Read> HashReader<D, R> {
101 pub fn finalize_reset(&mut self) -> Output<D> {
103 Digest::finalize_reset(&mut self.hasher)
104 }
105
106 pub fn finalize_into_reset(&mut self, out: &mut Output<D>) {
108 Digest::finalize_into_reset(&mut self.hasher, out)
109 }
110}
111
112impl<D: Digest + Reset, R: io::Read> Reset for HashReader<D, R> {
113 fn reset(&mut self) {
114 Digest::reset(&mut self.hasher)
115 }
116}
117
118impl<D: Digest, R: io::BufRead> HashReader<D, R> {
119 pub fn hash_to_end(&mut self) {
122 loop {
123 let count = {
124 let data = self.reader.fill_buf().unwrap();
125 if data.is_empty() {
126 break;
127 }
128
129 self.hasher.update(data);
130 data.len()
131 };
132
133 self.reader.consume(count);
134 }
135 }
136}