#![cfg(feature = "alloc")]
use dsi_bitstream::dispatch::{
CodeLen, Codes, ConstCode, DynamicCodeRead, DynamicCodeWrite, FuncCodeLen, FuncCodeReader,
FuncCodeWriter, StaticCodeRead, StaticCodeWrite, code_consts,
};
use dsi_bitstream::prelude::*;
const CODES: &[Codes] = &[
Codes::Unary,
Codes::Gamma,
Codes::Delta,
Codes::Omega,
Codes::VByteLe,
Codes::VByteBe,
Codes::Zeta(1),
Codes::Zeta(2),
Codes::Zeta(3),
Codes::Zeta(6),
Codes::Pi(0),
Codes::Pi(1),
Codes::Pi(3),
Codes::Golomb(1),
Codes::Golomb(3),
Codes::Golomb(7),
Codes::ExpGolomb(0),
Codes::ExpGolomb(2),
Codes::ExpGolomb(5),
Codes::Rice(0),
Codes::Rice(3),
Codes::Rice(7),
];
const VALUES: &[u64] = &[0, 1, 2, 7, 100, 1000, 100_000];
fn encode<E, F>(f: F) -> (usize, Vec<u64>)
where
E: Endianness,
BufBitWriter<E, MemWordWriterVec<u64, Vec<u64>>>: BitWrite<E> + CodesWrite<E>,
F: FnOnce(&mut BufBitWriter<E, MemWordWriterVec<u64, Vec<u64>>>) -> usize,
{
let mut w = BufBitWriter::<E, _>::new(MemWordWriterVec::new(Vec::<u64>::new()));
let bits = f(&mut w);
(bits, w.into_inner().unwrap().into_inner())
}
fn check_matrix<E: Endianness>()
where
BufBitWriter<E, MemWordWriterVec<u64, Vec<u64>>>: BitWrite<E> + CodesWrite<E>,
BufBitReader<E, MemWordReader<u64, Vec<u64>, true>>: BitRead<E> + CodesRead<E>,
{
for &code in CODES {
let fr = FuncCodeReader::<E, _>::new(code).unwrap();
let fw = FuncCodeWriter::<E, _>::new(code).unwrap();
let fl = FuncCodeLen::new(code).unwrap();
for &n in VALUES {
let (bits_dyn, buf_dyn) =
encode::<E, _>(|w| DynamicCodeWrite::write(&code, w, n).unwrap());
let (bits_fw, buf_fw) = encode::<E, _>(|w| StaticCodeWrite::write(&fw, w, n).unwrap());
assert_eq!(
bits_dyn, bits_fw,
"writer length mismatch for {code:?} n={n}"
);
assert_eq!(
buf_dyn, buf_fw,
"writer codeword mismatch for {code:?} n={n}"
);
assert_eq!(
bits_dyn,
code.len(n),
"Codes::len mismatch for {code:?} n={n}"
);
assert_eq!(
bits_dyn,
fl.get_func()(n),
"FuncCodeLen mismatch for {code:?} n={n}"
);
let mut r_dyn = BufBitReader::<E, _>::new(MemWordReader::new_inf(buf_dyn));
assert_eq!(
StaticCodeRead::read(&fr, &mut r_dyn).unwrap(),
n,
"FuncCodeReader on dynamic-encoded buffer for {code:?} n={n}"
);
let mut r_fw = BufBitReader::<E, _>::new(MemWordReader::new_inf(buf_fw));
assert_eq!(
DynamicCodeRead::read(&code, &mut r_fw).unwrap(),
n,
"Codes::read on func-encoded buffer for {code:?} n={n}"
);
}
}
}
#[test]
fn test_dispatch_matrix_be() {
check_matrix::<BE>();
}
#[test]
fn test_dispatch_matrix_le() {
check_matrix::<LE>();
}
#[test]
fn test_const_code_roundtrips() {
const N: u64 = 100;
macro_rules! rt {
($c:expr) => {{
let code = ConstCode::<{ $c }>;
let mut w = BufBitWriter::<BE, _>::new(MemWordWriterVec::new(Vec::<u64>::new()));
let bits = StaticCodeWrite::write(&code, &mut w, N).unwrap();
let buf = w.into_inner().unwrap().into_inner();
assert_eq!(bits, code.len(N), "ConstCode len mismatch for const {}", $c);
let mut r = BufBitReader::<BE, _>::new(MemWordReader::new_inf(buf));
assert_eq!(
StaticCodeRead::read(&code, &mut r).unwrap(),
N,
"ConstCode roundtrip mismatch for const {}",
$c
);
}};
}
rt!(code_consts::UNARY);
rt!(code_consts::GAMMA);
rt!(code_consts::DELTA);
rt!(code_consts::OMEGA);
rt!(code_consts::VBYTE_BE);
rt!(code_consts::VBYTE_LE);
rt!(code_consts::ZETA3);
}