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 Default for Crc { default() -> Self27 fn default() -> Self { 28 Self::new() 29 } 30 } 31 32 impl Crc { 33 /// Create a new CRC. new() -> Crc34 pub fn new() -> Crc { 35 Crc { 36 amt: 0, 37 hasher: Hasher::new(), 38 } 39 } 40 41 /// Returns the current crc32 checksum. sum(&self) -> u3242 pub fn sum(&self) -> u32 { 43 self.hasher.clone().finalize() 44 } 45 46 /// The number of bytes that have been used to calculate the CRC. 47 /// This value is only accurate if the amount is lower than 2<sup>32</sup>. amount(&self) -> u3248 pub fn amount(&self) -> u32 { 49 self.amt 50 } 51 52 /// Update the CRC with the bytes in `data`. update(&mut self, data: &[u8])53 pub fn update(&mut self, data: &[u8]) { 54 self.amt = self.amt.wrapping_add(data.len() as u32); 55 self.hasher.update(data); 56 } 57 58 /// Reset the CRC. reset(&mut self)59 pub fn reset(&mut self) { 60 self.amt = 0; 61 self.hasher.reset(); 62 } 63 64 /// Combine the CRC with the CRC for the subsequent block of bytes. combine(&mut self, additional_crc: &Crc)65 pub fn combine(&mut self, additional_crc: &Crc) { 66 self.amt = self.amt.wrapping_add(additional_crc.amt); 67 self.hasher.combine(&additional_crc.hasher); 68 } 69 } 70 71 impl<R: Read> CrcReader<R> { 72 /// Create a new `CrcReader`. new(r: R) -> CrcReader<R>73 pub fn new(r: R) -> CrcReader<R> { 74 CrcReader { 75 inner: r, 76 crc: Crc::new(), 77 } 78 } 79 } 80 81 impl<R> CrcReader<R> { 82 /// Get the Crc for this `CrcReader`. crc(&self) -> &Crc83 pub fn crc(&self) -> &Crc { 84 &self.crc 85 } 86 87 /// Get the reader that is wrapped by this `CrcReader`. into_inner(self) -> R88 pub fn into_inner(self) -> R { 89 self.inner 90 } 91 92 /// Get the reader that is wrapped by this `CrcReader` by reference. get_ref(&self) -> &R93 pub fn get_ref(&self) -> &R { 94 &self.inner 95 } 96 97 /// Get a mutable reference to the reader that is wrapped by this `CrcReader`. get_mut(&mut self) -> &mut R98 pub fn get_mut(&mut self) -> &mut R { 99 &mut self.inner 100 } 101 102 /// Reset the Crc in this `CrcReader`. reset(&mut self)103 pub fn reset(&mut self) { 104 self.crc.reset(); 105 } 106 } 107 108 impl<R: Read> Read for CrcReader<R> { read(&mut self, into: &mut [u8]) -> io::Result<usize>109 fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { 110 let amt = self.inner.read(into)?; 111 self.crc.update(&into[..amt]); 112 Ok(amt) 113 } 114 } 115 116 impl<R: BufRead> BufRead for CrcReader<R> { fill_buf(&mut self) -> io::Result<&[u8]>117 fn fill_buf(&mut self) -> io::Result<&[u8]> { 118 self.inner.fill_buf() 119 } consume(&mut self, amt: usize)120 fn consume(&mut self, amt: usize) { 121 if let Ok(data) = self.inner.fill_buf() { 122 self.crc.update(&data[..amt]); 123 } 124 self.inner.consume(amt); 125 } 126 } 127 128 /// A wrapper around a [`Write`] that calculates the CRC. 129 /// 130 /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html 131 #[derive(Debug)] 132 pub struct CrcWriter<W> { 133 inner: W, 134 crc: Crc, 135 } 136 137 impl<W> CrcWriter<W> { 138 /// Get the Crc for this `CrcWriter`. crc(&self) -> &Crc139 pub fn crc(&self) -> &Crc { 140 &self.crc 141 } 142 143 /// Get the writer that is wrapped by this `CrcWriter`. into_inner(self) -> W144 pub fn into_inner(self) -> W { 145 self.inner 146 } 147 148 /// Get the writer that is wrapped by this `CrcWriter` by reference. get_ref(&self) -> &W149 pub fn get_ref(&self) -> &W { 150 &self.inner 151 } 152 153 /// Get a mutable reference to the writer that is wrapped by this `CrcWriter`. get_mut(&mut self) -> &mut W154 pub fn get_mut(&mut self) -> &mut W { 155 &mut self.inner 156 } 157 158 /// Reset the Crc in this `CrcWriter`. reset(&mut self)159 pub fn reset(&mut self) { 160 self.crc.reset(); 161 } 162 } 163 164 impl<W: Write> CrcWriter<W> { 165 /// Create a new `CrcWriter`. new(w: W) -> CrcWriter<W>166 pub fn new(w: W) -> CrcWriter<W> { 167 CrcWriter { 168 inner: w, 169 crc: Crc::new(), 170 } 171 } 172 } 173 174 impl<W: Write> Write for CrcWriter<W> { write(&mut self, buf: &[u8]) -> io::Result<usize>175 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 176 let amt = self.inner.write(buf)?; 177 self.crc.update(&buf[..amt]); 178 Ok(amt) 179 } 180 flush(&mut self) -> io::Result<()>181 fn flush(&mut self) -> io::Result<()> { 182 self.inner.flush() 183 } 184 } 185