inflate/
checksum.rs

1use adler32::RollingAdler32;
2
3pub fn adler32_from_bytes(bytes: &[u8; 4]) -> u32 {
4    (bytes[3] as u32) | ((bytes[2] as u32) << 8) |
5       ((bytes[1] as u32) << 16) | ((bytes[0] as u32) << 24)
6}
7
8/// Whether we should validate the checksum, and what type of checksum it is.
9pub enum ChecksumType {
10    /// No validation.
11    ///
12    /// For raw deflate streams or when we don't bother checking.
13    None,
14    /// Adler32
15    ///
16    /// Used in the zlib format.
17    Adler32(RollingAdler32),
18}
19
20pub struct Checksum {
21    checksum_type: ChecksumType,
22}
23
24impl Checksum {
25    #[inline]
26    pub fn none() -> Checksum {
27        Checksum::new(ChecksumType::None)
28    }
29
30    #[inline]
31    pub fn is_none(&self) -> bool {
32        match self.checksum_type {
33            ChecksumType::None => true,
34            _ => false,
35        }
36    }
37
38    #[inline]
39    pub fn zlib() -> Checksum {
40        Checksum::new(ChecksumType::Adler32(RollingAdler32::new()))
41    }
42
43    pub fn new(checksum_type: ChecksumType) -> Checksum {
44        Checksum {
45            checksum_type: checksum_type,
46        }
47    }
48
49    #[inline]
50    pub fn update(&mut self, bytes: &[u8]) {
51        match self.checksum_type {
52            ChecksumType::None => (),
53            ChecksumType::Adler32(ref mut c) => {
54                c.update_buffer(bytes);
55            }
56        }
57    }
58
59    pub fn check(&self, expected: u32) -> Result<(), String> {
60        match self.checksum_type {
61            ChecksumType::None => Ok(()),
62            ChecksumType::Adler32(ref c) => {
63                if c.hash() == expected {
64                    Ok(())
65                } else {
66                    Err("Checksum mismatch!".to_owned())
67                }
68            },
69        }
70
71    }
72
73    #[inline]
74    pub fn current_value(&self) -> u32 {
75        match self.checksum_type {
76            ChecksumType::Adler32(ref c) => c.hash(),
77            _ => 0,
78        }
79    }
80
81}
82
83#[cfg(test)]
84mod test {
85    use super::adler32_from_bytes;
86
87    #[test]
88    fn adler32() {
89        let bytes = [0x00, 0x00, 0x01, 0x0b];
90        assert_eq!(adler32_from_bytes(&bytes), 267);
91    }
92}