use crate::core::dictionary::Dictionary;
#[inline(always)]
#[allow(dead_code)] pub fn has_ssse3() -> bool {
#[cfg(target_arch = "x86_64")]
{
is_x86_feature_detected!("ssse3")
}
#[cfg(not(target_arch = "x86_64"))]
{
false
}
}
#[inline(always)]
pub fn calculate_blocks(data_len: usize, block_size: usize) -> (usize, usize) {
let num_blocks = data_len / block_size;
let simd_bytes = num_blocks * block_size;
(num_blocks, simd_bytes)
}
#[inline]
pub fn encode_scalar_chunked(data: &[u8], dictionary: &Dictionary, result: &mut String) {
let base = dictionary.base();
let bits_per_char = (base as f64).log2() as usize;
if bits_per_char == 0 || bits_per_char > 8 {
return;
}
let mut bit_buffer = 0u32;
let mut bits_in_buffer = 0usize;
let mask = (1u32 << bits_per_char) - 1;
for &byte in data {
bit_buffer = (bit_buffer << 8) | (byte as u32);
bits_in_buffer += 8;
while bits_in_buffer >= bits_per_char {
bits_in_buffer -= bits_per_char;
let index = ((bit_buffer >> bits_in_buffer) & mask) as usize;
if let Some(ch) = dictionary.encode_digit(index) {
result.push(ch);
}
}
}
if bits_in_buffer > 0 {
let index = ((bit_buffer << (bits_per_char - bits_in_buffer)) & mask) as usize;
if let Some(ch) = dictionary.encode_digit(index) {
result.push(ch);
}
}
if let Some(pad_char) = dictionary.padding() {
let input_bits = data.len() * 8;
let output_chars = input_bits.div_ceil(bits_per_char);
if base == 64 {
while !result.len().is_multiple_of(4) {
result.push(pad_char);
}
} else {
while result.len() < output_chars {
result.push(pad_char);
}
}
}
}
pub fn decode_scalar_chunked<F>(
data: &[u8],
char_to_index: &mut F,
result: &mut Vec<u8>,
bits_per_char: usize,
) -> bool
where
F: FnMut(u8) -> Option<u8> + ?Sized,
{
let mut bit_buffer = 0u32;
let mut bits_in_buffer = 0usize;
for &byte in data {
let index = match char_to_index(byte) {
Some(i) => i as u32,
None => return false,
};
bit_buffer = (bit_buffer << bits_per_char) | index;
bits_in_buffer += bits_per_char;
if bits_in_buffer >= 8 {
bits_in_buffer -= 8;
let output_byte = (bit_buffer >> bits_in_buffer) as u8;
result.push(output_byte);
bit_buffer &= (1 << bits_in_buffer) - 1;
}
}
true
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calculate_blocks() {
assert_eq!(calculate_blocks(48, 16), (3, 48));
assert_eq!(calculate_blocks(50, 16), (3, 48));
assert_eq!(calculate_blocks(10, 16), (0, 0));
assert_eq!(calculate_blocks(0, 16), (0, 0));
}
#[test]
fn test_has_ssse3() {
let _ = has_ssse3();
}
}