1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//! # rscompress-checksums
//!
//! `rscompress_checksums` implements dfferent checksum algorithms for bytes.
//! checksums can be added to the compressed data.
//! This can then be used to check up if the deconstructed data is the same
//! as the original data.
use std::error::Error;
use std::fmt;

mod adler32;
mod crc32;

pub use adler32::Adler32;
pub use crc32::CRC32;

/// Trait for calculating checksums from binary data
pub trait Checksum {
    fn update(&mut self, data: &[u8]) -> Option<usize>;
    fn checksum(&self) -> Result<u32, ChecksumError>;
}

/// An enum representing possible errors during checksum calculation
#[derive(Debug)]
pub enum ChecksumError {
    /// The final checksum can not be calculated
    NoChecksum,
    /// Error during updating of the checksums
    UpdateError,
}

impl Error for ChecksumError {
    fn description(&self) -> &str {
        match *self {
            ChecksumError::NoChecksum => "No checksum",
            ChecksumError::UpdateError => "No update",
        }
    }
}

impl fmt::Display for ChecksumError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ChecksumError::NoChecksum => write!(f, "Can not calculate checksum"),
            ChecksumError::UpdateError => write!(f, "Can not update checksum"),
        }
    }
}

#[macro_export]
macro_rules! test_checksum {
    ($func_name:ident, $method:ident, $test_string:expr, $expected:expr) => {
        #[test]
        fn $func_name() {
            let mut a = $method::new();
            let data = $test_string.as_bytes();
            a.update(&data);
            assert_eq!(a.checksum().unwrap(), $expected)
        }
    };
}