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