1use digest::{Digest, FixedOutputReset, Output, Reset};
2use std::io;
3
4#[derive(Debug)]
6pub struct HashWriter<D: Digest, W: io::Write> {
7 writer: W,
8 hasher: D,
9}
10
11impl<D: Digest, W: io::Write> HashWriter<D, W> {
12 pub fn new(writer: W) -> Self {
14 Self::new_from_parts(D::new(), writer)
15 }
16
17 pub fn new_from_parts(hasher: D, writer: W) -> Self {
19 HashWriter { writer, hasher }
20 }
21
22 pub fn replace_writer(&mut self, writer: W) {
24 self.writer = writer;
25 }
26
27 pub fn get_hasher(&self) -> &D {
29 &self.hasher
30 }
31
32 pub fn get_writer(&self) -> &W {
34 &self.writer
35 }
36
37 pub fn get_hasher_mut(&mut self) -> &mut D {
40 &mut self.hasher
41 }
42
43 pub fn get_writer_mut(&mut self) -> &mut W {
46 &mut self.writer
47 }
48
49 pub fn into_hasher(self) -> D {
51 self.hasher
52 }
53
54 pub fn into_inner_writer(self) -> W {
56 self.writer
57 }
58
59 pub fn into_parts(self) -> (D, W) {
61 (self.hasher, self.writer)
62 }
63
64 pub fn finalize(self) -> Output<D> {
66 self.hasher.finalize()
67 }
68
69 pub fn finalize_into(self, out: &mut Output<D>) {
71 self.hasher.finalize_into(out)
72 }
73
74 pub fn output_size() -> usize {
76 <D as Digest>::output_size()
77 }
78}
79
80impl<D: Digest + Clone, W: io::Write + Clone> Clone for HashWriter<D, W> {
81 fn clone(&self) -> HashWriter<D, W> {
82 HashWriter {
83 writer: self.writer.clone(),
84 hasher: self.hasher.clone(),
85 }
86 }
87}
88
89impl<D: Digest, W: io::Write> io::Write for HashWriter<D, W> {
90 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
91 let bytes = self.writer.write(buf)?;
92
93 if bytes > 0 {
94 self.hasher.update(&buf[0..bytes]);
95 }
96
97 Ok(bytes)
98 }
99
100 fn flush(&mut self) -> io::Result<()> {
101 self.writer.flush()
102 }
103}
104
105impl<D: Digest + FixedOutputReset, W: io::Write> HashWriter<D, W> {
106 pub fn finalize_reset(&mut self) -> Output<D> {
108 Digest::finalize_reset(&mut self.hasher)
109 }
110
111 pub fn finalize_into_reset(&mut self, out: &mut Output<D>) {
113 Digest::finalize_into_reset(&mut self.hasher, out)
114 }
115}
116
117impl<D: Digest + Reset, W: io::Write> Reset for HashWriter<D, W> {
118 fn reset(&mut self) {
119 Digest::reset(&mut self.hasher)
120 }
121}