gzip_header/
crc_reader.rs1use std::fmt;
4use std::io;
5use std::io::{BufRead, Read};
6
7use crc32fast::Hasher;
8
9#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
12pub struct Crc {
13 checksum: u32,
16 amt: u32,
17}
18
19impl fmt::Display for Crc {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 write!(f, "({:#x},{})", self.checksum, self.amt)
22 }
23}
24
25#[derive(Debug)]
28pub struct CrcReader<R> {
29 inner: R,
30 crc: Crc,
31}
32
33impl Crc {
34 pub const fn new() -> Crc {
36 Crc {
37 checksum: 0,
38 amt: 0,
39 }
40 }
41
42 pub const fn with_initial(checksum: u32, amt: u32) -> Crc {
43 Crc { checksum, amt }
44 }
45
46 pub const fn sum(&self) -> u32 {
48 self.checksum
49 }
50
51 pub const fn amt_as_u32(&self) -> u32 {
53 self.amt
54 }
55
56 pub fn update(&mut self, data: &[u8]) {
58 self.amt = self.amt.wrapping_add(data.len() as u32);
59 let mut h = Hasher::new_with_initial(self.checksum);
60 h.update(data);
61 self.checksum = h.finalize();
62 }
63
64 pub fn reset(&mut self) {
66 self.checksum = 0;
67 self.amt = 0;
68 }
69}
70
71impl<R: Read> CrcReader<R> {
72 pub fn new(r: R) -> CrcReader<R> {
74 CrcReader {
75 inner: r,
76 crc: Crc::new(),
77 }
78 }
79
80 pub fn crc(&self) -> &Crc {
82 &self.crc
83 }
84
85 pub fn into_inner(self) -> R {
87 self.inner
88 }
89
90 pub fn inner(&mut self) -> &mut R {
92 &mut self.inner
93 }
94
95 pub fn reset(&mut self) {
97 self.crc.reset();
98 }
99}
100
101impl<R: Read> Read for CrcReader<R> {
102 fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
103 let amt = self.inner.read(into)?;
104 self.crc.update(&into[..amt]);
105 Ok(amt)
106 }
107}
108
109impl<R: BufRead> BufRead for CrcReader<R> {
110 fn fill_buf(&mut self) -> io::Result<&[u8]> {
111 self.inner.fill_buf()
112 }
113 fn consume(&mut self, amt: usize) {
114 if let Ok(data) = self.inner.fill_buf() {
115 self.crc.update(&data[..amt]);
116 }
117 self.inner.consume(amt);
118 }
119}
120
121#[cfg(test)]
122mod test {
123 use super::Crc;
124 #[test]
125 fn checksum_correct() {
126 let mut c = Crc::new();
127 c.update(b"abcdefg12345689\n");
128 assert_eq!(c.sum(), 0x141ddb83);
129 assert_eq!(c.amt_as_u32(), 16);
130 }
131}