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)]
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 Default for Crc {
27    fn default() -> Self {
28        Self::new()
29    }
30}
31
32impl Crc {
33    /// Create a new CRC.
34    pub fn new() -> Crc {
35        Crc {
36            amt: 0,
37            hasher: Hasher::new(),
38        }
39    }
40
41    /// Returns the current crc32 checksum.
42    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>.
48    pub fn amount(&self) -> u32 {
49        self.amt
50    }
51
52    /// Update the CRC with the bytes in `data`.
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.
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.
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
71impl<R: Read> CrcReader<R> {
72    /// Create a new `CrcReader`.
73    pub fn new(r: R) -> CrcReader<R> {
74        CrcReader {
75            inner: r,
76            crc: Crc::new(),
77        }
78    }
79}
80
81impl<R> CrcReader<R> {
82    /// Get the Crc for this `CrcReader`.
83    pub fn crc(&self) -> &Crc {
84        &self.crc
85    }
86
87    /// Get the reader that is wrapped by this `CrcReader`.
88    pub fn into_inner(self) -> R {
89        self.inner
90    }
91
92    /// Get the reader that is wrapped by this `CrcReader` by reference.
93    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`.
98    pub fn get_mut(&mut self) -> &mut R {
99        &mut self.inner
100    }
101
102    /// Reset the Crc in this `CrcReader`.
103    pub fn reset(&mut self) {
104        self.crc.reset();
105    }
106}
107
108impl<R: Read> Read for CrcReader<R> {
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
116impl<R: BufRead> BufRead for CrcReader<R> {
117    fn fill_buf(&mut self) -> io::Result<&[u8]> {
118        self.inner.fill_buf()
119    }
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)]
132pub struct CrcWriter<W> {
133    inner: W,
134    crc: Crc,
135}
136
137impl<W> CrcWriter<W> {
138    /// Get the Crc for this `CrcWriter`.
139    pub fn crc(&self) -> &Crc {
140        &self.crc
141    }
142
143    /// Get the writer that is wrapped by this `CrcWriter`.
144    pub fn into_inner(self) -> W {
145        self.inner
146    }
147
148    /// Get the writer that is wrapped by this `CrcWriter` by reference.
149    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`.
154    pub fn get_mut(&mut self) -> &mut W {
155        &mut self.inner
156    }
157
158    /// Reset the Crc in this `CrcWriter`.
159    pub fn reset(&mut self) {
160        self.crc.reset();
161    }
162}
163
164impl<W: Write> CrcWriter<W> {
165    /// Create a new `CrcWriter`.
166    pub fn new(w: W) -> CrcWriter<W> {
167        CrcWriter {
168            inner: w,
169            crc: Crc::new(),
170        }
171    }
172}
173
174impl<W: Write> Write for CrcWriter<W> {
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
181    fn flush(&mut self) -> io::Result<()> {
182        self.inner.flush()
183    }
184}