#![allow(dead_code)]
use super::hybrid_uint::HybridUintConfig;
use super::lz77::Lz77Params;
use super::token::{Lz77UintCoder, Token, UintCoder};
use crate::bit_writer::BitWriter;
use crate::error::Result;
use super::token::EncodedUint;
pub use super::encode_ans::*;
pub use super::encode_huffman::*;
#[inline]
pub(super) fn encode_token_value(token: &Token, lz77: Option<&Lz77Params>) -> (EncodedUint, u32) {
if token.is_lz77_length() {
let lz77 = lz77.expect("LZ77 length token without LZ77 params");
let encoded = Lz77UintCoder::encode(token.value);
let sym = encoded.token + lz77.min_symbol;
(encoded, sym)
} else {
let encoded = UintCoder::encode(token.value);
(encoded, encoded.token)
}
}
#[inline]
pub(super) fn encode_token_value_with_config(
token: &Token,
lz77: Option<&Lz77Params>,
config: &HybridUintConfig,
) -> (EncodedUint, u32) {
if token.is_lz77_length() {
let lz77 = lz77.expect("LZ77 length token without LZ77 params");
let encoded = Lz77UintCoder::encode(token.value);
let sym = encoded.token + lz77.min_symbol;
(encoded, sym)
} else {
let (tok, bits, nbits) = config.encode(token.value);
let encoded = EncodedUint {
token: tok,
nbits,
bits,
};
(encoded, tok)
}
}
pub(super) const CODE_LENGTH_CODES: usize = 18;
pub const ALPHABET_SIZE: usize = 64;
#[derive(Clone, Copy)]
pub struct PrefixCode {
pub depths: [u8; ALPHABET_SIZE],
pub bits: [u16; ALPHABET_SIZE],
}
impl Default for PrefixCode {
fn default() -> Self {
Self {
depths: [0; ALPHABET_SIZE],
bits: [0; ALPHABET_SIZE],
}
}
}
impl std::fmt::Debug for PrefixCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PrefixCode")
.field("depths", &&self.depths[..])
.field("bits", &&self.bits[..])
.finish()
}
}
#[derive(Debug, Clone, Copy)]
pub struct EntropyCode<'a> {
pub context_map: &'a [u8],
pub num_contexts: usize,
pub prefix_codes: &'a [PrefixCode],
pub num_prefix_codes: usize,
}
impl<'a> EntropyCode<'a> {
pub const fn new(context_map: &'a [u8], prefix_codes: &'a [PrefixCode]) -> Self {
Self {
context_map,
num_contexts: context_map.len(),
prefix_codes,
num_prefix_codes: prefix_codes.len(),
}
}
}
#[inline]
pub fn write_token(
token: &Token,
code: &EntropyCode,
lz77: Option<&Lz77Params>,
writer: &mut BitWriter,
) -> Result<()> {
let (encoded, sym) = encode_token_value(token, lz77);
let prefix_idx = code.context_map[token.context() as usize] as usize;
let pc = &code.prefix_codes[prefix_idx];
let tok = sym as usize;
let depth = pc.depths[tok] as usize;
let bits = pc.bits[tok] as u64;
let data = bits | ((encoded.bits as u64) << depth);
let total_bits = depth + encoded.nbits as usize;
writer.write(total_bits, data)
}
pub(super) fn write_var_len_uint16(n: usize, writer: &mut BitWriter) -> Result<()> {
debug_assert!(n <= 65535);
if n == 0 {
writer.write(1, 0)?;
} else {
writer.write(1, 1)?;
let nbits = floor_log2_nonzero(n as u32);
writer.write(4, nbits as u64)?;
writer.write(nbits as usize, (n - (1 << nbits)) as u64)?;
}
Ok(())
}
pub(super) fn floor_log2_nonzero(n: u32) -> u32 {
debug_assert!(n > 0);
31 - n.leading_zeros()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prefix_code_default() {
let pc = PrefixCode::default();
for i in 0..ALPHABET_SIZE {
assert_eq!(pc.depths[i], 0);
assert_eq!(pc.bits[i], 0);
}
}
}