use cxx::UniquePtr;
use crate::FastPForResult;
use crate::codec::{AnyLenCodec, BlockCodec64};
use crate::cpp::ffi;
use crate::cpp::wrappers::{
decode32_anylen_ffi, decode64_to_vec_ffi, encode32_to_vec_ffi, encode64_to_vec_ffi,
};
macro_rules! implement_cpp_codecs {
($(
$(#[$($attrs:tt)*])*
$name:ident => $ffi:ident ,
)*) => {
$(
$(#[$($attrs)*])*
pub struct $name(UniquePtr<ffi::IntegerCODEC>);
impl $name {
#[must_use]
pub fn new() -> Self {
Self(ffi::$ffi())
}
}
impl Default for $name {
fn default() -> Self {
Self::new()
}
}
impl AnyLenCodec for $name {
fn encode(&mut self, input: &[u32], out: &mut Vec<u32>) -> FastPForResult<()> {
encode32_to_vec_ffi(&self.0, input, out)
}
fn decode(
&mut self,
input: &[u32],
out: &mut Vec<u32>,
expected_len: Option<u32>,
) -> FastPForResult<()> {
decode32_anylen_ffi(&self.0, input, out, expected_len)
}
}
)*
#[cfg(test)]
#[allow(non_snake_case)]
mod cpp_default {
$(
#[test]
fn $name() {
let _codec = $crate::cpp::$name::default();
}
)*
}
#[cfg(test)]
#[allow(non_snake_case)]
mod cpp_short_roundtrip {
$(
#[test]
fn $name() {
$crate::test_utils::roundtrip::<$crate::cpp::$name>(&[1u32, 2, 3, 4, 5]);
}
)*
}
#[cfg(test)]
#[allow(non_snake_case)]
mod cpp_128bit_roundtrip {
$(
#[test]
fn $name() {
let input: Vec<u32> = (1..=128).collect();
$crate::test_utils::roundtrip::<$crate::cpp::$name>(&input);
}
)*
}
};
}
implement_cpp_codecs! {
CppBP32 => BP32_codec,
CppCopy => copy_codec,
CppFastBinaryPacking8 => fastbinarypacking8_codec,
CppFastBinaryPacking16 => fastbinarypacking16_codec,
CppFastBinaryPacking32 => fastbinarypacking32_codec,
CppFastPFor128 => fastpfor128_codec,
CppFastPFor256 => fastpfor256_codec,
CppMaskedVByte => maskedvbyte_codec,
CppNewPFor => newpfor_codec,
CppOptPFor => optpfor_codec,
CppPFor2008 => pfor2008_codec,
CppPFor => pfor_codec,
CppSimdBinaryPacking => simdbinarypacking_codec,
CppSimdFastPFor128 => simdfastpfor128_codec,
CppSimdFastPFor256 => simdfastpfor256_codec,
CppSimdGroupSimple => simdgroupsimple_codec,
CppSimdGroupSimpleRingBuf => simdgroupsimple_ringbuf_codec,
CppSimdNewPFor => simdnewpfor_codec,
CppSimdOptPFor => simdoptpfor_codec,
CppSimdPFor => simdpfor_codec,
CppSimdSimplePFor => simdsimplepfor_codec,
CppSimple16 => simple16_codec,
CppSimple8b => simple8b_codec,
CppSimple8bRle => simple8b_rle_codec,
CppSimple9 => simple9_codec,
CppSimple9Rle => simple9_rle_codec,
CppSimplePFor => simplepfor_codec,
CppStreamVByte => streamvbyte_codec,
CppVByte => vbyte_codec,
CppVarInt => varint_codec,
CppVarIntGb => varintgb_codec,
}
macro_rules! implement_cpp_codecs_64 {
($($name:ident => $ffi:ident ,)*) => {
$(
impl BlockCodec64 for $name {
fn encode64(&mut self, input: &[u64], out: &mut Vec<u32>) -> FastPForResult<()> {
encode64_to_vec_ffi(&self.0, input, out)
}
fn decode64(&mut self, input: &[u32], out: &mut Vec<u64>) -> FastPForResult<()> {
decode64_to_vec_ffi(&self.0, input, out)
}
}
)*
};
}
implement_cpp_codecs_64! {
CppFastPFor128 => fastpfor128_codec,
CppFastPFor256 => fastpfor256_codec,
CppVarInt => varint_codec,
}
#[cfg(test)]
pub(crate) mod tests {
use crate::cpp::codecs::{CppFastPFor128, CppFastPFor256, CppVByte, CppVarInt};
use crate::test_utils::{decompress, decompress64, roundtrip, roundtrip64};
#[test]
fn test_cpp_fastpfor256_composite_anylen() {
roundtrip::<CppFastPFor256>(&[1, 2, 3, 4, 5]);
let data: Vec<u32> = (0..600).collect();
roundtrip::<CppFastPFor256>(&data);
}
#[test]
fn test_fastpfor128_anylen() {
let data: Vec<u32> = (0..128).collect();
roundtrip::<CppFastPFor128>(&data);
}
#[test]
fn test_fastpfor256_anylen() {
let data: Vec<u32> = (0..256).collect();
roundtrip::<CppFastPFor256>(&data);
}
#[test]
fn test_fastpfor256_u64() {
let input: Vec<u64> = (0..256).collect();
roundtrip64::<CppFastPFor256>(&input);
}
#[test]
fn test_varint_u64() {
roundtrip64::<CppVarInt>(&[1u64, 2, 3, 4, 5]);
}
#[test]
fn test_decode32_empty_input() {
assert!(decompress::<CppVByte>(&[], None).unwrap().is_empty());
}
#[test]
fn test_decode32_cpp_empty_format() {
let result = decompress::<CppFastPFor128>(&[0u32], Some(0)).unwrap();
assert!(result.is_empty());
}
#[test]
fn test_decode64_empty_input() {
assert!(decompress64::<CppFastPFor256>(&[]).unwrap().is_empty());
}
#[test]
fn test_decode64_empty_format() {
assert!(decompress64::<CppVarInt>(&[]).unwrap().is_empty());
}
#[test]
fn test_decode_empty_input() {
assert!(decompress::<CppFastPFor128>(&[], None).unwrap().is_empty());
}
}