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: usize = self.inner.read(buf: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: &[u8]) = 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: usize = 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}
185