1 //! Helper module to compute a CRC32 checksum 2 3 use std::io; 4 use std::io::prelude::*; 5 6 use crc32fast::Hasher; 7 8 /// Reader that validates the CRC32 when it reaches the EOF. 9 pub struct Crc32Reader<R> { 10 inner: R, 11 hasher: Hasher, 12 check: u32, 13 /// Signals if `inner` stores aes encrypted data. 14 /// AE-2 encrypted data doesn't use crc and sets the value to 0. 15 ae2_encrypted: bool, 16 } 17 18 impl<R> Crc32Reader<R> { 19 /// Get a new Crc32Reader which checks the inner reader against checksum. 20 /// The check is disabled if `ae2_encrypted == true`. new(inner: R, checksum: u32, ae2_encrypted: bool) -> Crc32Reader<R>21 pub(crate) fn new(inner: R, checksum: u32, ae2_encrypted: bool) -> Crc32Reader<R> { 22 Crc32Reader { 23 inner, 24 hasher: Hasher::new(), 25 check: checksum, 26 ae2_encrypted, 27 } 28 } 29 check_matches(&self) -> bool30 fn check_matches(&self) -> bool { 31 self.check == self.hasher.clone().finalize() 32 } 33 into_inner(self) -> R34 pub fn into_inner(self) -> R { 35 self.inner 36 } 37 } 38 39 impl<R: Read> Read for Crc32Reader<R> { read(&mut self, buf: &mut [u8]) -> io::Result<usize>40 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { 41 let invalid_check = !buf.is_empty() && !self.check_matches() && !self.ae2_encrypted; 42 43 let count = match self.inner.read(buf) { 44 Ok(0) if invalid_check => { 45 return Err(io::Error::new(io::ErrorKind::Other, "Invalid checksum")) 46 } 47 Ok(n) => n, 48 Err(e) => return Err(e), 49 }; 50 self.hasher.update(&buf[0..count]); 51 Ok(count) 52 } 53 } 54 55 #[cfg(test)] 56 mod test { 57 use super::*; 58 use std::io::Read; 59 60 #[test] test_empty_reader()61 fn test_empty_reader() { 62 let data: &[u8] = b""; 63 let mut buf = [0; 1]; 64 65 let mut reader = Crc32Reader::new(data, 0, false); 66 assert_eq!(reader.read(&mut buf).unwrap(), 0); 67 68 let mut reader = Crc32Reader::new(data, 1, false); 69 assert!(reader 70 .read(&mut buf) 71 .unwrap_err() 72 .to_string() 73 .contains("Invalid checksum")); 74 } 75 76 #[test] test_byte_by_byte()77 fn test_byte_by_byte() { 78 let data: &[u8] = b"1234"; 79 let mut buf = [0; 1]; 80 81 let mut reader = Crc32Reader::new(data, 0x9be3e0a3, false); 82 assert_eq!(reader.read(&mut buf).unwrap(), 1); 83 assert_eq!(reader.read(&mut buf).unwrap(), 1); 84 assert_eq!(reader.read(&mut buf).unwrap(), 1); 85 assert_eq!(reader.read(&mut buf).unwrap(), 1); 86 assert_eq!(reader.read(&mut buf).unwrap(), 0); 87 // Can keep reading 0 bytes after the end 88 assert_eq!(reader.read(&mut buf).unwrap(), 0); 89 } 90 91 #[test] test_zero_read()92 fn test_zero_read() { 93 let data: &[u8] = b"1234"; 94 let mut buf = [0; 5]; 95 96 let mut reader = Crc32Reader::new(data, 0x9be3e0a3, false); 97 assert_eq!(reader.read(&mut buf[..0]).unwrap(), 0); 98 assert_eq!(reader.read(&mut buf).unwrap(), 4); 99 } 100 } 101