use crate::bytes;
use crate::crc32_table::{TABLE, TABLE16};
#[derive(Clone, Copy, Debug)]
pub struct CheckSummer {
sse42: bool,
}
impl CheckSummer {
#[cfg(not(target_arch = "x86_64"))]
pub fn new() -> CheckSummer {
CheckSummer { sse42: false }
}
#[cfg(target_arch = "x86_64")]
pub fn new() -> CheckSummer {
CheckSummer { sse42: is_x86_feature_detected!("sse4.2") }
}
pub fn crc32c_masked(&self, buf: &[u8]) -> u32 {
let sum = self.crc32c(buf);
(sum.wrapping_shr(15) | sum.wrapping_shl(17)).wrapping_add(0xA282EAD8)
}
#[cfg(not(target_arch = "x86_64"))]
fn crc32c(&self, buf: &[u8]) -> u32 {
crc32c_slice16(buf)
}
#[cfg(target_arch = "x86_64")]
fn crc32c(&self, buf: &[u8]) -> u32 {
if self.sse42 {
unsafe { crc32c_sse(buf) }
} else {
crc32c_slice16(buf)
}
}
}
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "sse4.2")]
unsafe fn crc32c_sse(buf: &[u8]) -> u32 {
use std::arch::x86_64::*;
let mut crc = !0u32;
let (prefix, u64s, suffix) = buf.align_to::<u64>();
for &b in prefix {
crc = _mm_crc32_u8(crc, b);
}
for &n in u64s {
crc = _mm_crc32_u64(crc as u64, n) as u32;
}
for &b in suffix {
crc = _mm_crc32_u8(crc, b);
}
!crc
}
fn crc32c_slice16(mut buf: &[u8]) -> u32 {
let mut crc: u32 = !0;
while buf.len() >= 16 {
crc ^= bytes::read_u32_le(buf);
crc = TABLE16[0][buf[15] as usize]
^ TABLE16[1][buf[14] as usize]
^ TABLE16[2][buf[13] as usize]
^ TABLE16[3][buf[12] as usize]
^ TABLE16[4][buf[11] as usize]
^ TABLE16[5][buf[10] as usize]
^ TABLE16[6][buf[9] as usize]
^ TABLE16[7][buf[8] as usize]
^ TABLE16[8][buf[7] as usize]
^ TABLE16[9][buf[6] as usize]
^ TABLE16[10][buf[5] as usize]
^ TABLE16[11][buf[4] as usize]
^ TABLE16[12][(crc >> 24) as u8 as usize]
^ TABLE16[13][(crc >> 16) as u8 as usize]
^ TABLE16[14][(crc >> 8) as u8 as usize]
^ TABLE16[15][(crc) as u8 as usize];
buf = &buf[16..];
}
for &b in buf {
crc = TABLE[((crc as u8) ^ b) as usize] ^ (crc >> 8);
}
!crc
}