use std::fmt::Debug;
use num_traits::PrimInt;
use crate::MltResult;
use crate::codecs::rle::encode_rle;
use crate::decoder::{RleLayout, RleMeta};
pub(crate) fn apply_rle<T: PrimInt + Debug>(
data: &[T],
num_logical: usize,
layout: RleLayout,
target: &mut Vec<T>,
) -> MltResult<RleMeta> {
let (runs_vec, vals_vec) = encode_rle(data);
let num_rle_values = u32::try_from(num_logical)?;
target.clear();
let meta = match layout {
RleLayout::Split => {
target.extend_from_slice(&runs_vec);
target.extend_from_slice(&vals_vec);
RleMeta::Split {
runs: u32::try_from(runs_vec.len())?,
num_rle_values,
}
}
#[cfg(feature = "unstable-v2")]
RleLayout::Interleaved => {
target.reserve(runs_vec.len().saturating_mul(2));
for (&run, &val) in runs_vec.iter().zip(&vals_vec) {
target.push(run);
target.push(val);
}
RleMeta::Interleaved { num_rle_values }
}
};
Ok(meta)
}
#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, strum::EnumIter)]
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
#[cfg_attr(all(not(test), feature = "arbitrary"), derive(arbitrary::Arbitrary))]
pub enum LogicalEncoder {
#[default]
None,
Delta,
DeltaRle,
Rle,
}
#[cfg(test)]
mod tests {
use proptest::prelude::*;
use super::*;
use crate::decoder::stream::header01;
use crate::encoder::model::StreamCtx;
use crate::encoder::{Codecs, Encoder, EncoderConfig, ExplicitEncoder, IntEncoder};
use crate::test_helpers::{assert_empty, dec, parser};
proptest! {
#[test]
fn test_u32_logical_roundtrip(
values in prop::collection::vec(any::<u32>(), 0..100),
logical in any::<LogicalEncoder>(),
) {
let mut enc = Encoder::with_explicit(
EncoderConfig::default(),
ExplicitEncoder::all(IntEncoder::varint_with(logical)),
);
let mut codecs = Codecs::default();
let ctx = StreamCtx::prop_data("test");
codecs.write_int_stream(&values, &ctx, &mut enc).unwrap();
let parsed = assert_empty(header01::parse_stream(enc.data(), &mut parser()));
let decoded = parsed.decode_ints::<u32>(&mut dec()).unwrap();
prop_assert_eq!(decoded, values);
}
#[test]
fn test_i32_logical_roundtrip(
values in prop::collection::vec(any::<i32>(), 0..100),
logical in any::<LogicalEncoder>(),
) {
let mut enc = Encoder::with_explicit(
EncoderConfig::default(),
ExplicitEncoder::all(IntEncoder::varint_with(logical)),
);
let mut codecs = Codecs::default();
let ctx = StreamCtx::prop_data("test");
codecs.write_int_stream(&values, &ctx, &mut enc).unwrap();
let parsed = assert_empty(header01::parse_stream(enc.data(), &mut parser()));
let decoded = parsed.decode_ints::<i32>(&mut dec()).unwrap();
prop_assert_eq!(decoded, values);
}
#[test]
fn test_u64_logical_roundtrip(
values in prop::collection::vec(any::<u64>(), 0..100),
logical in any::<LogicalEncoder>(),
) {
let mut enc = Encoder::with_explicit(
EncoderConfig::default(),
ExplicitEncoder::all(IntEncoder::varint_with(logical)),
);
let mut codecs = Codecs::default();
let ctx = StreamCtx::prop_data("test");
codecs.write_int_stream(&values, &ctx, &mut enc).unwrap();
let parsed = assert_empty(header01::parse_stream(enc.data(), &mut parser()));
let decoded = parsed.decode_ints::<u64>(&mut dec()).unwrap();
prop_assert_eq!(decoded, values);
}
#[test]
fn test_i64_logical_roundtrip(
values in prop::collection::vec(any::<i64>(), 0..100),
logical in any::<LogicalEncoder>(),
) {
let mut enc = Encoder::with_explicit(
EncoderConfig::default(),
ExplicitEncoder::all(IntEncoder::varint_with(logical)),
);
let mut codecs = Codecs::default();
let ctx = StreamCtx::prop_data("test");
codecs.write_int_stream(&values, &ctx, &mut enc).unwrap();
let parsed = assert_empty(header01::parse_stream(enc.data(), &mut parser()));
let decoded = parsed.decode_ints::<i64>(&mut dec()).unwrap();
prop_assert_eq!(decoded, values);
}
}
}