From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/snap/src/crc32.rs | 111 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 vendor/snap/src/crc32.rs (limited to 'vendor/snap/src/crc32.rs') diff --git a/vendor/snap/src/crc32.rs b/vendor/snap/src/crc32.rs new file mode 100644 index 000000000..1298ef04a --- /dev/null +++ b/vendor/snap/src/crc32.rs @@ -0,0 +1,111 @@ +use crate::bytes; +use crate::crc32_table::{TABLE, TABLE16}; + +/// Provides a simple API to generate "masked" CRC32C checksums specifically +/// for use in Snappy. When available, this will make use of SSE 4.2 to compute +/// checksums. Otherwise, it falls back to only-marginally-slower "slicing by +/// 16" technique. +/// +/// The main purpose of this type is to cache the CPU feature check and expose +/// a safe API. +#[derive(Clone, Copy, Debug)] +pub struct CheckSummer { + sse42: bool, +} + +impl CheckSummer { + /// Create a new checksummer that can compute CRC32C checksums on arbitrary + /// bytes. + #[cfg(not(target_arch = "x86_64"))] + pub fn new() -> CheckSummer { + CheckSummer { sse42: false } + } + + /// Create a new checksummer that can compute CRC32C checksums on arbitrary + /// bytes. + #[cfg(target_arch = "x86_64")] + pub fn new() -> CheckSummer { + CheckSummer { sse42: is_x86_feature_detected!("sse4.2") } + } + + /// Returns the "masked" CRC32 checksum of `buf` using the Castagnoli + /// polynomial. This "masked" checksum is defined by the Snappy frame + /// format. Masking is supposed to make the checksum robust with respect to + /// the data that contains the checksum itself. + pub fn crc32c_masked(&self, buf: &[u8]) -> u32 { + let sum = self.crc32c(buf); + (sum.wrapping_shr(15) | sum.wrapping_shl(17)).wrapping_add(0xA282EAD8) + } + + /// Returns the CRC32 checksum of `buf` using the Castagnoli polynomial. + #[cfg(not(target_arch = "x86_64"))] + fn crc32c(&self, buf: &[u8]) -> u32 { + crc32c_slice16(buf) + } + + /// Returns the CRC32 checksum of `buf` using the Castagnoli polynomial. + #[cfg(target_arch = "x86_64")] + fn crc32c(&self, buf: &[u8]) -> u32 { + if self.sse42 { + // SAFETY: When sse42 is true, we are guaranteed to be running on + // a CPU that supports SSE 4.2. + 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; + // SAFETY: This is safe since alignment is handled by align_to (oh how I + // love you) and since 8 adjacent u8's are guaranteed to have the same + // in-memory representation as u64 for all possible values. + let (prefix, u64s, suffix) = buf.align_to::(); + for &b in prefix { + // SAFETY: Safe since we have sse4.2 enabled. + crc = _mm_crc32_u8(crc, b); + } + for &n in u64s { + // SAFETY: Safe since we have sse4.2 enabled. + crc = _mm_crc32_u64(crc as u64, n) as u32; + } + for &b in suffix { + // SAFETY: Safe since we have sse4.2 enabled. + crc = _mm_crc32_u8(crc, b); + } + !crc +} + +/// Returns the CRC32 checksum of `buf` using the Castagnoli polynomial. +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 +} -- cgit v1.2.3