gzip_header/
crc_reader.rs1use core::fmt;
4#[cfg(feature = "std")]
5use std::io;
6#[cfg(feature = "std")]
7use std::io::{BufRead, Read};
8
9use crc32fast::Hasher;
10
11#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
14pub struct Crc {
15 checksum: u32,
18 amt: u32,
19}
20
21impl fmt::Display for Crc {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 write!(f, "({:#x},{})", self.checksum, self.amt)
24 }
25}
26
27impl Crc {
28 pub const fn new() -> Crc {
30 Crc {
31 checksum: 0,
32 amt: 0,
33 }
34 }
35
36 pub const fn with_initial(checksum: u32, amt: u32) -> Crc {
37 Crc { checksum, amt }
38 }
39
40 pub const fn sum(&self) -> u32 {
42 self.checksum
43 }
44
45 pub const fn amt_as_u32(&self) -> u32 {
47 self.amt
48 }
49
50 pub fn update(&mut self, data: &[u8]) {
52 self.amt = self.amt.wrapping_add(data.len() as u32);
53 let mut h = Hasher::new_with_initial(self.checksum);
54 h.update(data);
55 self.checksum = h.finalize();
56 }
57
58 pub fn reset(&mut self) {
60 self.checksum = 0;
61 self.amt = 0;
62 }
63}
64
65#[cfg(feature = "std")]
68#[derive(Debug)]
69pub struct CrcReader<R> {
70 inner: R,
71 crc: Crc,
72}
73
74
75#[cfg(feature = "std")]
76impl<R: Read> CrcReader<R> {
77 pub fn new(r: R) -> CrcReader<R> {
79 CrcReader {
80 inner: r,
81 crc: Crc::new(),
82 }
83 }
84
85 pub fn crc(&self) -> &Crc {
87 &self.crc
88 }
89
90 pub fn into_inner(self) -> R {
92 self.inner
93 }
94
95 pub fn inner(&mut self) -> &mut R {
97 &mut self.inner
98 }
99
100 pub fn reset(&mut self) {
102 self.crc.reset();
103 }
104}
105
106#[cfg(feature = "std")]
107impl<R: Read> Read for CrcReader<R> {
108 fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
109 let amt = self.inner.read(into)?;
110 self.crc.update(&into[..amt]);
111 Ok(amt)
112 }
113}
114
115#[cfg(feature = "std")]
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#[cfg(test)]
129mod test {
130 use super::Crc;
131 #[test]
132 fn checksum_correct() {
133 let mut c = Crc::new();
134 c.update(b"abcdefg12345689\n");
135 assert_eq!(c.sum(), 0x141ddb83);
136 assert_eq!(c.amt_as_u32(), 16);
137 }
138}