1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
//! 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 += 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()
}
}