flate2/
crc.rs

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