mint_cli/output/
checksum.rs1use crate::layout::settings::CrcConfig;
2
3pub fn calculate_crc(data: &[u8], crc_settings: &CrcConfig) -> u32 {
7 let polynomial = crc_settings.polynomial.unwrap();
8 let start = crc_settings.start.unwrap();
9 let xor_out = crc_settings.xor_out.unwrap();
10 let ref_in = crc_settings.ref_in.unwrap();
11 let ref_out = crc_settings.ref_out.unwrap();
12
13 let mut crc = if ref_in { start.reverse_bits() } else { start };
15
16 let poly = if ref_in {
18 polynomial.reverse_bits()
19 } else {
20 polynomial
21 };
22
23 for &byte in data {
25 let idx = if ref_in {
26 (crc ^ (byte as u32)) & 0xFF
27 } else {
28 ((crc >> 24) ^ (byte as u32)) & 0xFF
29 };
30
31 let mut step = if ref_in { idx } else { idx << 24 };
33 if ref_in {
34 for _ in 0..8 {
35 step = (step >> 1) ^ ((step & 1) * poly);
36 }
37 } else {
38 for _ in 0..8 {
39 step = (step << 1) ^ (((step >> 31) & 1) * poly);
40 }
41 }
42
43 crc = if ref_in {
44 step ^ (crc >> 8)
45 } else {
46 step ^ (crc << 8)
47 };
48 }
49
50 if ref_in ^ ref_out {
52 crc = crc.reverse_bits();
53 }
54
55 crc ^ xor_out
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61 use crate::layout::settings::CrcArea;
62
63 fn standard_crc_config() -> CrcConfig {
64 CrcConfig {
65 location: None,
66 polynomial: Some(0x04C11DB7),
67 start: Some(0xFFFF_FFFF),
68 xor_out: Some(0xFFFF_FFFF),
69 ref_in: Some(true),
70 ref_out: Some(true),
71 area: Some(CrcArea::Data),
72 }
73 }
74
75 #[test]
77 fn test_crc32_standard_test_vector() {
78 let crc_settings = standard_crc_config();
79
80 let test_str = b"123456789";
82 let result = calculate_crc(test_str, &crc_settings);
83 assert_eq!(
84 result, 0xCBF43926,
85 "Standard CRC32 test vector failed (expected 0xCBF43926 for \"123456789\")"
86 );
87
88 let simple_data = vec![0x01, 0x02, 0x03, 0x04];
90 let simple_result = calculate_crc(&simple_data, &crc_settings);
91 assert_eq!(simple_result, 0xB63CFBCD, "CRC32 for [1,2,3,4] failed");
92 }
93
94 #[test]
95 fn test_crc32_mpeg2_non_reflected_vector() {
96 let crc_settings = CrcConfig {
97 location: None,
98 polynomial: Some(0x04C11DB7),
99 start: Some(0xFFFF_FFFF),
100 xor_out: Some(0x0000_0000),
101 ref_in: Some(false),
102 ref_out: Some(false),
103 area: Some(CrcArea::Data),
104 };
105
106 let test_str = b"123456789";
108 let result = calculate_crc(test_str, &crc_settings);
109 assert_eq!(
110 result, 0x0376E6E7,
111 "CRC32/MPEG-2 test vector failed (expected 0x0376E6E7 for \"123456789\")"
112 );
113 }
114}