|  | //! Simple CRC bindings backed by miniz.c | 
|  |  | 
|  | use std::io; | 
|  | use std::io::prelude::*; | 
|  |  | 
|  | use crc32fast::Hasher; | 
|  |  | 
|  | /// The CRC calculated by a [`CrcReader`]. | 
|  | /// | 
|  | /// [`CrcReader`]: struct.CrcReader.html | 
|  | #[derive(Debug)] | 
|  | pub struct Crc { | 
|  | amt: u32, | 
|  | hasher: Hasher, | 
|  | } | 
|  |  | 
|  | /// A wrapper around a [`Read`] that calculates the CRC. | 
|  | /// | 
|  | /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html | 
|  | #[derive(Debug)] | 
|  | pub struct CrcReader<R> { | 
|  | inner: R, | 
|  | crc: Crc, | 
|  | } | 
|  |  | 
|  | impl Default for Crc { | 
|  | fn default() -> Self { | 
|  | Self::new() | 
|  | } | 
|  | } | 
|  |  | 
|  | impl Crc { | 
|  | /// Create a new CRC. | 
|  | pub fn new() -> Crc { | 
|  | Crc { | 
|  | amt: 0, | 
|  | hasher: Hasher::new(), | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Returns the current crc32 checksum. | 
|  | pub fn sum(&self) -> u32 { | 
|  | self.hasher.clone().finalize() | 
|  | } | 
|  |  | 
|  | /// The number of bytes that have been used to calculate the CRC. | 
|  | /// This value is only accurate if the amount is lower than 2<sup>32</sup>. | 
|  | pub fn amount(&self) -> u32 { | 
|  | self.amt | 
|  | } | 
|  |  | 
|  | /// Update the CRC with the bytes in `data`. | 
|  | pub fn update(&mut self, data: &[u8]) { | 
|  | self.amt = self.amt.wrapping_add(data.len() as u32); | 
|  | self.hasher.update(data); | 
|  | } | 
|  |  | 
|  | /// Reset the CRC. | 
|  | pub fn reset(&mut self) { | 
|  | self.amt = 0; | 
|  | self.hasher.reset(); | 
|  | } | 
|  |  | 
|  | /// Combine the CRC with the CRC for the subsequent block of bytes. | 
|  | pub fn combine(&mut self, additional_crc: &Crc) { | 
|  | self.amt = self.amt.wrapping_add(additional_crc.amt); | 
|  | self.hasher.combine(&additional_crc.hasher); | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<R: Read> CrcReader<R> { | 
|  | /// Create a new `CrcReader`. | 
|  | pub fn new(r: R) -> CrcReader<R> { | 
|  | CrcReader { | 
|  | inner: r, | 
|  | crc: Crc::new(), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<R> CrcReader<R> { | 
|  | /// Get the Crc for this `CrcReader`. | 
|  | pub fn crc(&self) -> &Crc { | 
|  | &self.crc | 
|  | } | 
|  |  | 
|  | /// Get the reader that is wrapped by this `CrcReader`. | 
|  | pub fn into_inner(self) -> R { | 
|  | self.inner | 
|  | } | 
|  |  | 
|  | /// Get the reader that is wrapped by this `CrcReader` by reference. | 
|  | pub fn get_ref(&self) -> &R { | 
|  | &self.inner | 
|  | } | 
|  |  | 
|  | /// Get a mutable reference to the reader that is wrapped by this `CrcReader`. | 
|  | pub fn get_mut(&mut self) -> &mut R { | 
|  | &mut self.inner | 
|  | } | 
|  |  | 
|  | /// Reset the Crc in this `CrcReader`. | 
|  | pub fn reset(&mut self) { | 
|  | self.crc.reset(); | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<R: Read> Read for CrcReader<R> { | 
|  | fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { | 
|  | let amt = self.inner.read(into)?; | 
|  | self.crc.update(&into[..amt]); | 
|  | Ok(amt) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<R: BufRead> BufRead for CrcReader<R> { | 
|  | fn fill_buf(&mut self) -> io::Result<&[u8]> { | 
|  | self.inner.fill_buf() | 
|  | } | 
|  | fn consume(&mut self, amt: usize) { | 
|  | if let Ok(data) = self.inner.fill_buf() { | 
|  | self.crc.update(&data[..amt]); | 
|  | } | 
|  | self.inner.consume(amt); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// A wrapper around a [`Write`] that calculates the CRC. | 
|  | /// | 
|  | /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html | 
|  | #[derive(Debug)] | 
|  | pub struct CrcWriter<W> { | 
|  | inner: W, | 
|  | crc: Crc, | 
|  | } | 
|  |  | 
|  | impl<W> CrcWriter<W> { | 
|  | /// Get the Crc for this `CrcWriter`. | 
|  | pub fn crc(&self) -> &Crc { | 
|  | &self.crc | 
|  | } | 
|  |  | 
|  | /// Get the writer that is wrapped by this `CrcWriter`. | 
|  | pub fn into_inner(self) -> W { | 
|  | self.inner | 
|  | } | 
|  |  | 
|  | /// Get the writer that is wrapped by this `CrcWriter` by reference. | 
|  | pub fn get_ref(&self) -> &W { | 
|  | &self.inner | 
|  | } | 
|  |  | 
|  | /// Get a mutable reference to the writer that is wrapped by this `CrcWriter`. | 
|  | pub fn get_mut(&mut self) -> &mut W { | 
|  | &mut self.inner | 
|  | } | 
|  |  | 
|  | /// Reset the Crc in this `CrcWriter`. | 
|  | pub fn reset(&mut self) { | 
|  | self.crc.reset(); | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<W: Write> CrcWriter<W> { | 
|  | /// Create a new `CrcWriter`. | 
|  | pub fn new(w: W) -> CrcWriter<W> { | 
|  | CrcWriter { | 
|  | inner: w, | 
|  | crc: Crc::new(), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<W: Write> Write for CrcWriter<W> { | 
|  | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | 
|  | let amt = self.inner.write(buf)?; | 
|  | self.crc.update(&buf[..amt]); | 
|  | Ok(amt) | 
|  | } | 
|  |  | 
|  | fn flush(&mut self) -> io::Result<()> { | 
|  | self.inner.flush() | 
|  | } | 
|  | } |