use crc32c::{crc32c, crc32c_append};
#[cfg(test)]
use crate::constants::MIB;
pub(crate) fn crc32c_zeroed_checksum(data: &[u8]) -> u32 {
let crc = crc32c(&data[..4]);
let crc = crc32c_append(crc, &[0; 4]);
crc32c_append(crc, &data[8..])
}
#[must_use]
pub(crate) fn compute_chunk_ratio(block_size: u64, logical_sector_size: u64) -> u64 {
(1u64 << 23) * logical_sector_size / block_size
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn crc32c_zeroed_checksum_zeroes_field_before_compute() {
let mut data = vec![0xFFu8; 16];
data[4..8].copy_from_slice(&0xDEAD_BEEFu32.to_le_bytes());
let result = crc32c_zeroed_checksum(&data);
let mut expected_buf = data.clone();
expected_buf[4..8].fill(0);
let expected = crc32c(&expected_buf);
assert_eq!(result, expected);
}
#[test]
fn crc32c_zeroed_checksum_does_not_mutate_original() {
let mut data = vec![0xFFu8; 16];
data[4..8].copy_from_slice(&0x1234_5678_u32.to_le_bytes());
let original = data.clone();
let _ = crc32c_zeroed_checksum(&data);
assert_eq!(data, original);
}
#[test]
fn crc32c_zeroed_checksum_all_zeros() {
let data = vec![0u8; 8];
let result = crc32c_zeroed_checksum(&data);
assert_eq!(result, crc32c(&data));
}
#[test]
fn compute_chunk_ratio_standard_values() {
assert_eq!(compute_chunk_ratio(32 * u64::from(MIB), 4096), 1024);
assert_eq!(compute_chunk_ratio(u64::from(MIB), 4096), 32768);
assert_eq!(compute_chunk_ratio(256 * u64::from(MIB), 512), 16);
}
#[test]
fn compute_chunk_ratio_large_block_small_sector() {
let small = compute_chunk_ratio(256 * u64::from(MIB), 512);
let large = compute_chunk_ratio(u64::from(MIB), 512);
assert!(
small < large,
"larger blocks should produce smaller chunk ratio"
);
}
}