1 //! Simple CRC bindings backed by miniz.c
2 
3 use std::io;
4 use std::io::prelude::*;
5 
6 use crc32fast::Hasher;
7 
8 /// The CRC calculated by a [`CrcReader`].
9 ///
10 /// [`CrcReader`]: struct.CrcReader.html
11 #[derive(Debug)]
12 pub struct Crc {
13     amt: u32,
14     hasher: Hasher,
15 }
16 
17 /// A wrapper around a [`Read`] that calculates the CRC.
18 ///
19 /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
20 #[derive(Debug)]
21 pub struct CrcReader<R> {
22     inner: R,
23     crc: Crc,
24 }
25 
26 impl Crc {
27     /// Create a new CRC.
new() -> Crc28     pub fn new() -> Crc {
29         Crc {
30             amt: 0,
31             hasher: Hasher::new(),
32         }
33     }
34 
35     /// Returns the current crc32 checksum.
sum(&self) -> u3236     pub fn sum(&self) -> u32 {
37         self.hasher.clone().finalize()
38     }
39 
40     /// The number of bytes that have been used to calculate the CRC.
41     /// This value is only accurate if the amount is lower than 2<sup>32</sup>.
amount(&self) -> u3242     pub fn amount(&self) -> u32 {
43         self.amt
44     }
45 
46     /// Update the CRC with the bytes in `data`.
update(&mut self, data: &[u8])47     pub fn update(&mut self, data: &[u8]) {
48         self.amt = self.amt.wrapping_add(data.len() as u32);
49         self.hasher.update(data);
50     }
51 
52     /// Reset the CRC.
reset(&mut self)53     pub fn reset(&mut self) {
54         self.amt = 0;
55         self.hasher.reset();
56     }
57 
58     /// Combine the CRC with the CRC for the subsequent block of bytes.
combine(&mut self, additional_crc: &Crc)59     pub fn combine(&mut self, additional_crc: &Crc) {
60         self.amt += additional_crc.amt;
61         self.hasher.combine(&additional_crc.hasher);
62     }
63 }
64 
65 impl<R: Read> CrcReader<R> {
66     /// Create a new CrcReader.
new(r: R) -> CrcReader<R>67     pub fn new(r: R) -> CrcReader<R> {
68         CrcReader {
69             inner: r,
70             crc: Crc::new(),
71         }
72     }
73 }
74 
75 impl<R> CrcReader<R> {
76     /// Get the Crc for this CrcReader.
crc(&self) -> &Crc77     pub fn crc(&self) -> &Crc {
78         &self.crc
79     }
80 
81     /// Get the reader that is wrapped by this CrcReader.
into_inner(self) -> R82     pub fn into_inner(self) -> R {
83         self.inner
84     }
85 
86     /// Get the reader that is wrapped by this CrcReader by reference.
get_ref(&self) -> &R87     pub fn get_ref(&self) -> &R {
88         &self.inner
89     }
90 
91     /// Get a mutable reference to the reader that is wrapped by this CrcReader.
get_mut(&mut self) -> &mut R92     pub fn get_mut(&mut self) -> &mut R {
93         &mut self.inner
94     }
95 
96     /// Reset the Crc in this CrcReader.
reset(&mut self)97     pub fn reset(&mut self) {
98         self.crc.reset();
99     }
100 }
101 
102 impl<R: Read> Read for CrcReader<R> {
read(&mut self, into: &mut [u8]) -> io::Result<usize>103     fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
104         let amt = self.inner.read(into)?;
105         self.crc.update(&into[..amt]);
106         Ok(amt)
107     }
108 }
109 
110 impl<R: BufRead> BufRead for CrcReader<R> {
fill_buf(&mut self) -> io::Result<&[u8]>111     fn fill_buf(&mut self) -> io::Result<&[u8]> {
112         self.inner.fill_buf()
113     }
consume(&mut self, amt: usize)114     fn consume(&mut self, amt: usize) {
115         if let Ok(data) = self.inner.fill_buf() {
116             self.crc.update(&data[..amt]);
117         }
118         self.inner.consume(amt);
119     }
120 }
121 
122 /// A wrapper around a [`Write`] that calculates the CRC.
123 ///
124 /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
125 #[derive(Debug)]
126 pub struct CrcWriter<W> {
127     inner: W,
128     crc: Crc,
129 }
130 
131 impl<W> CrcWriter<W> {
132     /// Get the Crc for this CrcWriter.
crc(&self) -> &Crc133     pub fn crc(&self) -> &Crc {
134         &self.crc
135     }
136 
137     /// Get the writer that is wrapped by this CrcWriter.
into_inner(self) -> W138     pub fn into_inner(self) -> W {
139         self.inner
140     }
141 
142     /// Get the writer that is wrapped by this CrcWriter by reference.
get_ref(&self) -> &W143     pub fn get_ref(&self) -> &W {
144         &self.inner
145     }
146 
147     /// Get a mutable reference to the writer that is wrapped by this CrcWriter.
get_mut(&mut self) -> &mut W148     pub fn get_mut(&mut self) -> &mut W {
149         &mut self.inner
150     }
151 
152     /// Reset the Crc in this CrcWriter.
reset(&mut self)153     pub fn reset(&mut self) {
154         self.crc.reset();
155     }
156 }
157 
158 impl<W: Write> CrcWriter<W> {
159     /// Create a new CrcWriter.
new(w: W) -> CrcWriter<W>160     pub fn new(w: W) -> CrcWriter<W> {
161         CrcWriter {
162             inner: w,
163             crc: Crc::new(),
164         }
165     }
166 }
167 
168 impl<W: Write> Write for CrcWriter<W> {
write(&mut self, buf: &[u8]) -> io::Result<usize>169     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
170         let amt = self.inner.write(buf)?;
171         self.crc.update(&buf[..amt]);
172         Ok(amt)
173     }
174 
flush(&mut self) -> io::Result<()>175     fn flush(&mut self) -> io::Result<()> {
176         self.inner.flush()
177     }
178 }
179