]>
Commit | Line | Data |
---|---|---|
7cac9316 XL |
1 | //! Simple CRC bindings backed by miniz.c |
2 | ||
3 | use std::io::prelude::*; | |
4 | use std::io; | |
5 | use libc; | |
6 | ||
7 | use ffi; | |
8 | ||
ea8adc8c XL |
9 | /// The CRC calculated by a [`CrcReader`]. |
10 | /// | |
11 | /// [`CrcReader`]: struct.CrcReader.html | |
12 | #[derive(Debug)] | |
7cac9316 XL |
13 | pub struct Crc { |
14 | crc: libc::c_ulong, | |
15 | amt: u32, | |
16 | } | |
17 | ||
ea8adc8c XL |
18 | /// A wrapper around a [`Read`] that calculates the CRC. |
19 | /// | |
20 | /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html | |
21 | #[derive(Debug)] | |
7cac9316 XL |
22 | pub struct CrcReader<R> { |
23 | inner: R, | |
24 | crc: Crc, | |
25 | } | |
26 | ||
27 | impl Crc { | |
28 | /// Create a new CRC. | |
29 | pub fn new() -> Crc { | |
30 | Crc { crc: 0, amt: 0 } | |
31 | } | |
32 | ||
33 | /// bla | |
34 | pub fn sum(&self) -> u32 { | |
35 | self.crc as u32 | |
36 | } | |
37 | ||
38 | /// The number of bytes that have been used to calculate the CRC. | |
39 | /// This value is only accurate if the amount is lower than 2^32. | |
40 | pub fn amount(&self) -> u32 { | |
41 | self.amt | |
42 | } | |
43 | ||
44 | /// Update the CRC with the bytes in `data`. | |
45 | pub fn update(&mut self, data: &[u8]) { | |
46 | self.amt = self.amt.wrapping_add(data.len() as u32); | |
47 | self.crc = unsafe { | |
48 | ffi::mz_crc32(self.crc, data.as_ptr(), data.len() as libc::size_t) | |
49 | }; | |
50 | } | |
51 | ||
52 | /// Reset the CRC. | |
53 | pub fn reset(&mut self) { | |
54 | self.crc = 0; | |
55 | self.amt = 0; | |
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.crc = unsafe { | |
61 | ffi::mz_crc32_combine(self.crc as ::libc::c_ulong, | |
62 | additional_crc.crc as ::libc::c_ulong, | |
63 | additional_crc.amt as ::libc::off_t) | |
64 | }; | |
65 | self.amt += additional_crc.amt; | |
66 | } | |
67 | } | |
68 | ||
69 | impl<R: Read> CrcReader<R> { | |
70 | /// Create a new CrcReader. | |
71 | pub fn new(r: R) -> CrcReader<R> { | |
72 | CrcReader { | |
73 | inner: r, | |
74 | crc: Crc::new(), | |
75 | } | |
76 | } | |
ea8adc8c | 77 | } |
7cac9316 | 78 | |
ea8adc8c | 79 | impl<R> CrcReader<R> { |
7cac9316 XL |
80 | /// Get the Crc for this CrcReader. |
81 | pub fn crc(&self) -> &Crc { | |
82 | &self.crc | |
83 | } | |
84 | ||
85 | /// Get the reader that is wrapped by this CrcReader. | |
86 | pub fn into_inner(self) -> R { | |
87 | self.inner | |
88 | } | |
89 | ||
90 | /// Get the reader that is wrapped by this CrcReader by reference. | |
91 | pub fn get_ref(&self) -> &R { | |
92 | &self.inner | |
93 | } | |
94 | ||
95 | /// Get a mutable reference to the reader that is wrapped by this CrcReader. | |
96 | pub fn get_mut(&mut self) -> &mut R { | |
97 | &mut self.inner | |
98 | } | |
99 | ||
100 | /// Reset the Crc in this CrcReader. | |
101 | pub fn reset(&mut self) { | |
102 | self.crc.reset(); | |
103 | } | |
104 | } | |
105 | ||
106 | impl<R: Read> Read for CrcReader<R> { | |
107 | fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { | |
108 | let amt = try!(self.inner.read(into)); | |
109 | self.crc.update(&into[..amt]); | |
110 | Ok(amt) | |
111 | } | |
112 | } | |
113 | ||
114 | impl<R: BufRead> BufRead for CrcReader<R> { | |
115 | fn fill_buf(&mut self) -> io::Result<&[u8]> { | |
116 | self.inner.fill_buf() | |
117 | } | |
118 | fn consume(&mut self, amt: usize) { | |
119 | if let Ok(data) = self.inner.fill_buf() { | |
120 | self.crc.update(&data[..amt]); | |
121 | } | |
122 | self.inner.consume(amt); | |
123 | } | |
124 | } |