draco_oxide_core/codec/entropy/
mod.rs1use crate::bit_coder::{ByteReader, ByteWriter, ReaderErr};
2
3pub mod rans;
4
5pub const L_RANS_BASE: usize = 4096;
6pub const DEFAULT_RANS_PRECISION: usize = 12;
7pub const DEFAULT_RABS_PRECISION: usize = 8;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum SymbolEncodingMethod {
11 #[allow(unused)]
12 LengthCoded,
13 DirectCoded,
14}
15
16impl SymbolEncodingMethod {
17 #[allow(unused)]
18 pub fn read_from<R>(reader: &mut R) -> Result<Self, Err>
19 where
20 R: ByteReader,
21 {
22 let method = reader.read_u8()?;
23 match method {
24 0 => Ok(SymbolEncodingMethod::LengthCoded),
25 1 => Ok(SymbolEncodingMethod::DirectCoded),
26 _ => Err(Err::InvalidSymbolEncodingMethod),
27 }
28 }
29 pub fn write_to<W>(&self, writer: &mut W)
30 where
31 W: ByteWriter,
32 {
33 match self {
34 SymbolEncodingMethod::LengthCoded => writer.write_u8(0),
35 SymbolEncodingMethod::DirectCoded => writer.write_u8(1),
36 }
37 }
38}
39
40pub struct RansSymbol {
41 pub freq_count: usize,
42 pub freq_cumulative: usize,
43}
44
45pub fn rans_build_tables<const RANS_PRECISION: usize>(
46 freq_counts: &[usize],
47) -> Result<(Vec<usize>, Vec<RansSymbol>), Err> {
48 let mut slot_table = Vec::with_capacity(1 << RANS_PRECISION);
49 let mut rans_syms = Vec::with_capacity(freq_counts.len());
50
51 let mut freq_cumulative = 0;
52 for (i, freq_count) in freq_counts.iter().enumerate() {
53 let symbol = RansSymbol {
54 freq_count: *freq_count,
55 freq_cumulative,
56 };
57 rans_syms.push(symbol);
58 let tmp = freq_cumulative;
59 freq_cumulative = freq_cumulative
60 .checked_add(*freq_count)
61 .ok_or(Err::InvalidFreqCount)?; for _ in tmp..freq_cumulative {
63 slot_table.push(i);
64 }
65 }
66
67 if freq_cumulative != 1 << RANS_PRECISION {
68 return Err(Err::FrequencyCountNotCompatibleWithRansPrecision(
69 freq_cumulative,
70 1 << RANS_PRECISION,
71 ));
72 }
73
74 Ok((slot_table, rans_syms))
75}
76
77#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)]
78pub enum Err {
79 #[error(
80 "Frequency count not compatible with RANS precision: freq_count=={0}!={1}==rans_precision"
81 )]
82 FrequencyCountNotCompatibleWithRansPrecision(usize, usize),
83 #[error("Invalid frequency count")]
84 InvalidFreqCount,
85 #[error("Invalid symbol encoding method")]
86 InvalidSymbolEncodingMethod,
87 #[error("Reader error")]
88 ReaderError(#[from] ReaderErr),
89}