Skip to main content

msrtc_rans/
entropy.rs

1// Licensed under the MIT license.
2// Author: Riaan de Beer - github.com/infinityabundance - rdebeer.infinityabundance@gmail.com
3// Derived from Microsoft MLVC msrtc_rans (MIT)
4// See NOTICE file for attribution.
5
6//! # Entropy encoder/decoder (high-level PMF/bypass/CDF pipeline)
7//!
8//! Implements the high-level entropy coder matching Microsoft's
9//! `EntropyEncoder` / `EntropyDecoder` in `EntropyCoder.cpp`.
10//!
11//! Builds on the raw rANS primitives from `msrtc-rans-core`.
12
13#![allow(missing_docs)]
14
15use alloc::vec::Vec;
16
17use msrtc_rans_core::sink::VecSink;
18use msrtc_rans_core::source::SliceSource;
19use msrtc_rans_core::source::Source;
20use msrtc_rans_core::variant::{Rans64, RansByte, RansParams};
21use msrtc_rans_core::{
22    Freq, Rans64DecSymbol, Rans64EncSymbol, Rans64Encoder, RansByteDecSymbol, RansByteEncSymbol,
23    RansByteEncoder, RawRansError,
24};
25
26// ---------------------------------------------------------------------------
27// Constants
28// ---------------------------------------------------------------------------
29
30/// Size of Freq in bits (sizeof(u32) * 8 = 32).
31const FREQ_BITS: u32 = (core::mem::size_of::<Freq>() * 8) as u32;
32
33// ---------------------------------------------------------------------------
34// Error types
35// ---------------------------------------------------------------------------
36
37/// Errors that can occur during entropy encode/decode operations.
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub enum EntropyError {
40    /// Invalid PMF data (lengths, offsets, or table).
41    InvalidPmf,
42    /// Invalid parameter value (symbolBits, bypassBits, etc.).
43    InvalidParams,
44    /// Encoder/decoder is not initialized.
45    InvalidState,
46    /// Stream data is truncated or corrupted.
47    InvalidStream,
48    /// Raw rANS primitive error.
49    RawRansError(RawRansError),
50}
51
52impl core::fmt::Display for EntropyError {
53    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54        match self {
55            EntropyError::InvalidPmf => write!(f, "invalid PMF data"),
56            EntropyError::InvalidParams => write!(f, "invalid parameter value"),
57            EntropyError::InvalidState => write!(f, "invalid state (not initialized)"),
58            EntropyError::InvalidStream => write!(f, "invalid stream"),
59            EntropyError::RawRansError(e) => write!(f, "raw rANS error: {}", e),
60        }
61    }
62}
63
64#[cfg(feature = "std")]
65impl std::error::Error for EntropyError {}
66
67// ---------------------------------------------------------------------------
68// Distribution descriptor
69// ---------------------------------------------------------------------------
70
71/// Describes one probability distribution (one set of PMF symbols).
72#[derive(Debug, Clone)]
73struct DistributionDesc {
74    /// Offset applied to input values for this distribution.
75    value_offset: i32,
76    /// Sentinel index = length - 1 (last PMF element is tail mass for bypass).
77    bypass_sentinel: i32,
78    /// Starting offset of this distribution in the global symbol/CDF table.
79    symbol_offset: usize,
80}
81
82// ---------------------------------------------------------------------------
83// Helper: validate distribution descriptors from PMF arrays
84// ---------------------------------------------------------------------------
85
86fn initialize_distribution_desc(
87    distribution_descs: &mut Vec<DistributionDesc>,
88    pmf_lengths: &[i32],
89    pmf_offsets: &[i32],
90    pmf_table_size: usize,
91) -> Result<(), EntropyError> {
92    let distribution_count = pmf_lengths.len();
93    if pmf_offsets.len() != distribution_count {
94        return Err(EntropyError::InvalidPmf);
95    }
96    distribution_descs.reserve(distribution_count);
97
98    let mut symbol_cursor: usize = 0;
99    for i in 0..distribution_count {
100        let length = pmf_lengths[i];
101        // Each length must be > 1 (last element is bypass tail mass)
102        if length <= 1 || pmf_table_size - symbol_cursor < length as usize {
103            return Err(EntropyError::InvalidPmf);
104        }
105        distribution_descs.push(DistributionDesc {
106            value_offset: pmf_offsets[i],
107            bypass_sentinel: length - 1,
108            symbol_offset: symbol_cursor,
109        });
110        symbol_cursor += length as usize;
111    }
112
113    if symbol_cursor != pmf_table_size {
114        return Err(EntropyError::InvalidPmf);
115    }
116    Ok(())
117}
118
119// ---------------------------------------------------------------------------
120// Helper: check probability bits against max
121// ---------------------------------------------------------------------------
122
123#[inline]
124fn check_bits(prob_bits: u32, max_scale_bits: u32) -> Result<(), EntropyError> {
125    if prob_bits < 2 || prob_bits > max_scale_bits {
126        return Err(EntropyError::InvalidParams);
127    }
128    Ok(())
129}
130
131// ---------------------------------------------------------------------------
132// Helper: convert byte slice to u32 units (LE)
133// ---------------------------------------------------------------------------
134
135#[inline]
136fn bytes_to_u32_units(data: &[u8]) -> Vec<u32> {
137    data.chunks_exact(4)
138        .map(|c| u32::from_le_bytes([c[0], c[1], c[2], c[3]]))
139        .collect()
140}
141
142// ---------------------------------------------------------------------------
143// Raw rANS encoder trait — abstracts RansByteEncoder and Rans64Encoder
144// ---------------------------------------------------------------------------
145
146/// Trait abstracting over raw rANS encoder variants for the entropy coder.
147pub(crate) trait RawEncoder {
148    type Unit: Copy + Default;
149    type Symbol;
150    fn put_raw(&mut self, start: Freq, freq: Freq, scale_bits: Freq);
151    fn put_symbol(&mut self, symbol: &Self::Symbol);
152    fn flush(&mut self);
153    fn into_units(self) -> Vec<Self::Unit>;
154}
155
156impl RawEncoder for RansByteEncoder<VecSink<u8>> {
157    type Unit = u8;
158    type Symbol = RansByteEncSymbol;
159
160    fn put_raw(&mut self, start: Freq, freq: Freq, scale_bits: Freq) {
161        self.put_raw(start, freq, scale_bits);
162    }
163
164    fn put_symbol(&mut self, symbol: &Self::Symbol) {
165        self.put(symbol);
166    }
167
168    fn flush(&mut self) {
169        self.flush();
170    }
171
172    fn into_units(self) -> Vec<u8> {
173        self.into_sink().encoded().to_vec()
174    }
175}
176
177impl RawEncoder for Rans64Encoder<VecSink<u32>> {
178    type Unit = u32;
179    type Symbol = Rans64EncSymbol;
180
181    fn put_raw(&mut self, start: Freq, freq: Freq, scale_bits: Freq) {
182        self.put_raw(start, freq, scale_bits);
183    }
184
185    fn put_symbol(&mut self, symbol: &Self::Symbol) {
186        self.put(symbol);
187    }
188
189    fn flush(&mut self) {
190        self.flush();
191    }
192
193    fn into_units(self) -> Vec<u32> {
194        self.into_sink().encoded().to_vec()
195    }
196}
197
198// ---------------------------------------------------------------------------
199// Internal encoder state — generic across variants
200// ---------------------------------------------------------------------------
201
202struct EncoderState<S: EncSymbol> {
203    symbol_bits: Freq,
204    distribution_descs: Vec<DistributionDesc>,
205    symbols: Vec<S>,
206    bypass_bits: Freq,
207    bypass_max_value: Freq,
208}
209
210/// Trait for encoder symbol types.
211pub(crate) trait EncSymbol: Sized {
212    fn try_new(start: Freq, freq: Freq, scale_bits: Freq) -> Result<Self, RawRansError>;
213}
214
215impl EncSymbol for RansByteEncSymbol {
216    fn try_new(start: Freq, freq: Freq, scale_bits: Freq) -> Result<Self, RawRansError> {
217        Self::try_new(start, freq, scale_bits)
218    }
219}
220
221impl EncSymbol for Rans64EncSymbol {
222    fn try_new(start: Freq, freq: Freq, scale_bits: Freq) -> Result<Self, RawRansError> {
223        Self::try_new(start, freq, scale_bits)
224    }
225}
226
227impl<S: EncSymbol> EncoderState<S> {
228    fn uninitialized() -> Self {
229        Self {
230            symbol_bits: 0,
231            distribution_descs: Vec::new(),
232            symbols: Vec::new(),
233            bypass_bits: 0,
234            bypass_max_value: 0,
235        }
236    }
237
238    fn initialize(
239        &mut self,
240        pmf_lengths: &[i32],
241        pmf_offsets: &[i32],
242        pmf_table: &[i32],
243        symbol_bits: i32,
244        bypass_bits: i32,
245        max_scale_bits: u32,
246    ) -> Result<(), EntropyError> {
247        let sb = symbol_bits as Freq;
248        let bb = bypass_bits as Freq;
249        check_bits(sb, max_scale_bits)?;
250        check_bits(bb, max_scale_bits)?;
251
252        // Issue 2a: safe maximum — RansByte allows 30, Rans64 allows 31 for bypass
253        let is_byte_variant = max_scale_bits < 32;
254        let max_safe_bits = if is_byte_variant { 30u32 } else { 31u32 };
255        if sb > max_safe_bits || bb > max_safe_bits {
256            return Err(EntropyError::InvalidParams);
257        }
258
259        let mut distribution_descs = Vec::new();
260        initialize_distribution_desc(
261            &mut distribution_descs,
262            pmf_lengths,
263            pmf_offsets,
264            pmf_table.len(),
265        )?;
266
267        // Issue 2b: use u64 for max_freq computation to avoid i32 overflow
268        let max_freq = 1u64 << symbol_bits;
269        let mut symbols: Vec<S> = Vec::with_capacity(pmf_table.len());
270        let mut pmf_cursor: usize = 0;
271
272        for desc in &distribution_descs {
273            // Issue 2b: track cumulative start in u64
274            let mut start: u64 = 0;
275            for _i in 0..=desc.bypass_sentinel {
276                let freq = pmf_table[pmf_cursor] as u64;
277                pmf_cursor += 1;
278                if !(freq > 0 && freq <= max_freq - start) {
279                    return Err(EntropyError::InvalidPmf);
280                }
281                let sym = S::try_new(start as Freq, freq as Freq, sb).map_err(|e| match e {
282                    RawRansError::InvalidScaleBits { .. } => EntropyError::InvalidParams,
283                    RawRansError::InvalidParameters => EntropyError::InvalidPmf,
284                })?;
285                symbols.push(sym);
286                start += freq;
287            }
288        }
289
290        self.distribution_descs = distribution_descs;
291        self.symbols = symbols;
292        self.symbol_bits = sb;
293        self.bypass_bits = bb;
294        // Issue 2c: compute from u64 to avoid overflow at bb=32
295        self.bypass_max_value = ((1u64 << bb) - 1) as Freq;
296        Ok(())
297    }
298
299    fn encode_to_vec<E: RawEncoder<Symbol = S>>(
300        &self,
301        indices: &[i32],
302        values: &[i32],
303        make_encoder: impl FnOnce() -> E,
304    ) -> Result<Vec<E::Unit>, EntropyError> {
305        if self.symbol_bits == 0 {
306            return Err(EntropyError::InvalidState);
307        }
308        if indices.len() != values.len() {
309            return Err(EntropyError::InvalidParams);
310        }
311
312        let mut encoder = make_encoder();
313
314        // Encode in reverse order (matching C++: iterate from last to first)
315        let data_size = indices.len();
316        let mut idx = data_size as isize - 1;
317        while idx >= 0 {
318            let index = indices[idx as usize];
319            let value = values[idx as usize];
320
321            if index < 0 {
322                // Skip encoding, decoder returns 0 for skipped indices
323                idx -= 1;
324                continue;
325            }
326
327            // Clamp distribution index to a valid range
328            let dist_len = self.distribution_descs.len();
329            let ui = if (index as usize) < dist_len {
330                index as usize
331            } else {
332                dist_len - 1
333            };
334            let desc = &self.distribution_descs[ui];
335
336            // Issue 5: checked add to avoid i32 overflow
337            let adjusted = value
338                .checked_add(desc.value_offset)
339                .ok_or(EntropyError::InvalidParams)?;
340            let symbol_index: i32;
341            if adjusted < 0 || adjusted >= desc.bypass_sentinel {
342                // Out of PMF range — use bypass
343                // Issue 5: use checked_neg and checked_mul for safety
344                let bypass_value: Freq = if adjusted < 0 {
345                    // 2 * (-value) - 1
346                    let neg = adjusted.checked_neg().ok_or(EntropyError::InvalidParams)?;
347                    2u64.wrapping_mul(neg as u64).wrapping_sub(1) as Freq
348                } else {
349                    2u64.wrapping_mul((adjusted - desc.bypass_sentinel) as u64) as Freq
350                };
351                self.encode_bypass_value(&mut encoder, bypass_value);
352                symbol_index = desc.bypass_sentinel;
353            } else {
354                symbol_index = adjusted;
355            }
356
357            let sym_idx = desc.symbol_offset + symbol_index as usize;
358            encoder.put_symbol(&self.symbols[sym_idx]);
359            idx -= 1;
360        }
361
362        encoder.flush();
363        Ok(encoder.into_units())
364    }
365
366    #[inline]
367    fn encode_bypass_value<E: RawEncoder>(&self, encoder: &mut E, bypass_value: Freq) {
368        // Split bypassValue into bypassBits-sized digits (LSB first)
369        let max_parts = (FREQ_BITS as usize / self.bypass_bits as usize).max(2);
370        let mut bypass_buffer = Vec::with_capacity(max_parts);
371
372        let mut bv = bypass_value;
373        while bv != 0 {
374            bypass_buffer.push(bv & self.bypass_max_value);
375            bv >>= self.bypass_bits;
376        }
377
378        let mut bypass_count = bypass_buffer.len() as Freq;
379
380        // Put digits in reverse order (MSB first in the bitstream)
381        // since the rANS encoder writes from end to start
382        for &digit in bypass_buffer.iter().rev() {
383            encoder.put_raw(digit, 1, self.bypass_bits);
384        }
385
386        // Encode bypass count as remainder-coded prefix
387        // (each maxValue digit means "more to follow")
388        let mut bypass_prefix_count: Freq = 0;
389        while bypass_count >= self.bypass_max_value {
390            bypass_count -= self.bypass_max_value;
391            bypass_prefix_count += 1;
392        }
393        // Put bypassCount remainder (terminal digit)
394        encoder.put_raw(bypass_count, 1, self.bypass_bits);
395        // Put bypassCount prefix markers
396        for _ in 0..bypass_prefix_count {
397            encoder.put_raw(self.bypass_max_value, 1, self.bypass_bits);
398        }
399    }
400}
401
402// ---------------------------------------------------------------------------
403// Internal decoder state — generic across variants
404// ---------------------------------------------------------------------------
405
406struct DecoderState {
407    symbol_bits: Freq,
408    distribution_descs: Vec<DistributionDesc>,
409    cdf_table: Vec<Freq>,
410    bypass_bits: Freq,
411    bypass_max_value: Freq,
412}
413
414impl DecoderState {
415    fn uninitialized() -> Self {
416        Self {
417            symbol_bits: 0,
418            distribution_descs: Vec::new(),
419            cdf_table: Vec::new(),
420            bypass_bits: 0,
421            bypass_max_value: 0,
422        }
423    }
424
425    fn initialize(
426        &mut self,
427        pmf_lengths: &[i32],
428        pmf_offsets: &[i32],
429        pmf_table: &[i32],
430        symbol_bits: i32,
431        bypass_bits: i32,
432        max_scale_bits: u32,
433    ) -> Result<(), EntropyError> {
434        let sb = symbol_bits as Freq;
435        let bb = bypass_bits as Freq;
436        check_bits(sb, max_scale_bits)?;
437        check_bits(bb, max_scale_bits)?;
438
439        // Issue 2a: safe maximum
440        let is_byte_variant = max_scale_bits < 32;
441        let max_safe_bits = if is_byte_variant { 30u32 } else { 31u32 };
442        if sb > max_safe_bits || bb > max_safe_bits {
443            return Err(EntropyError::InvalidParams);
444        }
445
446        let mut distribution_descs = Vec::new();
447        initialize_distribution_desc(
448            &mut distribution_descs,
449            pmf_lengths,
450            pmf_offsets,
451            pmf_table.len(),
452        )?;
453
454        // Build CDF table: for each distribution, store cumulative starts
455        // plus one extra entry per distribution for the total sum
456        let num_dist = distribution_descs.len();
457        let mut cdf_table = vec![0u32; pmf_table.len() + num_dist];
458        // Issue 2b: use u64 for max_freq
459        let max_freq = 1u64 << symbol_bits;
460
461        let mut cursor: usize = 0;
462        for dist_idx in 0..num_dist {
463            // Update symbol_offset to point into the CDF table (not the PMF table)
464            distribution_descs[dist_idx].symbol_offset = cursor + dist_idx;
465
466            let mut start: u64 = 0;
467            for _i in 0..=distribution_descs[dist_idx].bypass_sentinel {
468                let freq = pmf_table[cursor] as u64;
469                if !(freq > 0 && freq <= max_freq - start) {
470                    return Err(EntropyError::InvalidPmf);
471                }
472                cdf_table[cursor + dist_idx] = start as Freq;
473                start += freq;
474                cursor += 1;
475            }
476            cdf_table[cursor + dist_idx] = start as Freq; // total sum
477        }
478
479        self.distribution_descs = distribution_descs;
480        self.cdf_table = cdf_table;
481        self.symbol_bits = sb;
482        self.bypass_bits = bb;
483        // Issue 2c: compute from u64
484        self.bypass_max_value = ((1u64 << bb) - 1) as Freq;
485        Ok(())
486    }
487
488    fn decode_from_slice(
489        &self,
490        values: &mut [i32],
491        indices: &[i32],
492        data: &[u8],
493        is_byte_variant: bool,
494    ) -> Result<(), EntropyError> {
495        if self.symbol_bits == 0 {
496            return Err(EntropyError::InvalidState);
497        }
498        if values.len() != indices.len() {
499            return Err(EntropyError::InvalidParams);
500        }
501
502        if is_byte_variant {
503            let units = data.to_vec();
504            let source = SliceSource::new(&units);
505            let mut decoder = msrtc_rans_core::RansByteDecoder::new(source);
506            if !decoder.init() {
507                return Err(EntropyError::InvalidStream);
508            }
509            self.decode_inner_byte(&mut decoder, values, indices)?;
510            if !decoder.source().is_exhausted() || !decoder.check_eof() {
511                return Err(EntropyError::InvalidStream);
512            }
513        } else {
514            // Issue 3: Reject misaligned Rans64 streams (must be 4-byte aligned)
515            if data.len() % 4 != 0 {
516                return Err(EntropyError::InvalidStream);
517            }
518            let units = bytes_to_u32_units(data);
519            let source = SliceSource::new(&units);
520            let mut decoder = msrtc_rans_core::Rans64Decoder::new(source);
521            if !decoder.init() {
522                return Err(EntropyError::InvalidStream);
523            }
524            self.decode_inner_64(&mut decoder, values, indices)?;
525            if !decoder.source().is_exhausted() || !decoder.check_eof() {
526                return Err(EntropyError::InvalidStream);
527            }
528        }
529        Ok(())
530    }
531
532    /// Helper: decode bypass count using remainder-coded prefix for RansByte decoder.
533    #[inline]
534    fn decode_bypass_count_byte(
535        &self,
536        decoder: &mut msrtc_rans_core::RansByteDecoder<SliceSource<'_, u8>>,
537    ) -> Result<Freq, EntropyError> {
538        let mut total: Freq = 0;
539        loop {
540            let value = decoder.get(self.bypass_bits);
541            if !decoder.advance(value, 1, self.bypass_bits) {
542                return Err(EntropyError::InvalidStream);
543            }
544            total += value;
545            if value != self.bypass_max_value {
546                break;
547            }
548            if total > FREQ_BITS {
549                return Err(EntropyError::InvalidStream);
550            }
551        }
552        Ok(total)
553    }
554
555    /// Helper: decode bypass count for Rans64 decoder.
556    #[inline]
557    fn decode_bypass_count_64(
558        &self,
559        decoder: &mut msrtc_rans_core::Rans64Decoder<SliceSource<'_, u32>>,
560    ) -> Result<Freq, EntropyError> {
561        let mut total: Freq = 0;
562        loop {
563            let value = decoder.get(self.bypass_bits);
564            if !decoder.advance(value, 1, self.bypass_bits) {
565                return Err(EntropyError::InvalidStream);
566            }
567            total += value;
568            if value != self.bypass_max_value {
569                break;
570            }
571            if total > FREQ_BITS {
572                return Err(EntropyError::InvalidStream);
573            }
574        }
575        Ok(total)
576    }
577
578    /// Helper: decode bypass value for RansByte decoder.
579    #[inline]
580    fn decode_bypass_value_payload_byte(
581        &self,
582        decoder: &mut msrtc_rans_core::RansByteDecoder<SliceSource<'_, u8>>,
583        bypass_count: Freq,
584    ) -> Result<Freq, EntropyError> {
585        // Issue 2c: use u64 for intermediate value to avoid overflow on shift
586        let mut encoded_value: u64 = 0;
587        let total_bits = bypass_count as u64 * self.bypass_bits as u64;
588        let mut shift: u64 = 0;
589        while shift < total_bits {
590            let v = decoder.get(self.bypass_bits);
591            if !decoder.advance(v, 1, self.bypass_bits) {
592                return Err(EntropyError::InvalidStream);
593            }
594            encoded_value |= (v as u64) << shift;
595            shift += self.bypass_bits as u64;
596        }
597        Ok(encoded_value as Freq)
598    }
599
600    /// Helper: decode bypass value for Rans64 decoder.
601    #[inline]
602    fn decode_bypass_value_payload_64(
603        &self,
604        decoder: &mut msrtc_rans_core::Rans64Decoder<SliceSource<'_, u32>>,
605        bypass_count: Freq,
606    ) -> Result<Freq, EntropyError> {
607        // Issue 2c: use u64 for intermediate value to avoid overflow on shift
608        let mut encoded_value: u64 = 0;
609        let total_bits = bypass_count as u64 * self.bypass_bits as u64;
610        let mut shift: u64 = 0;
611        while shift < total_bits {
612            let v = decoder.get(self.bypass_bits);
613            if !decoder.advance(v, 1, self.bypass_bits) {
614                return Err(EntropyError::InvalidStream);
615            }
616            encoded_value |= (v as u64) << shift;
617            shift += self.bypass_bits as u64;
618        }
619        Ok(encoded_value as Freq)
620    }
621
622    fn decode_inner_byte(
623        &self,
624        decoder: &mut msrtc_rans_core::RansByteDecoder<SliceSource<'_, u8>>,
625        values: &mut [i32],
626        indices: &[i32],
627    ) -> Result<(), EntropyError> {
628        if self.symbol_bits == 0 {
629            return Err(EntropyError::InvalidState);
630        }
631        if values.len() != indices.len() {
632            return Err(EntropyError::InvalidParams);
633        }
634
635        for (i, &index) in indices.iter().enumerate() {
636            if index < 0 {
637                values[i] = 0;
638                continue;
639            }
640
641            let dist_len = self.distribution_descs.len();
642            let ui = if (index as usize) < dist_len {
643                index as usize
644            } else {
645                dist_len - 1
646            };
647            let desc = &self.distribution_descs[ui];
648
649            // Get cumulative frequency from state (low symbolBits bits)
650            let cum_freq = decoder.get(self.symbol_bits);
651            debug_assert!(cum_freq < (1u32 << self.symbol_bits));
652
653            // Binary search in CDF table to find the symbol
654            let base_offset = desc.symbol_offset;
655            let lo = base_offset + 1;
656            let hi = base_offset + desc.bypass_sentinel as usize + 1;
657
658            // upper_bound: first element > cum_freq
659            let upper_idx = {
660                let mut low = lo;
661                let mut high = hi;
662                while low < high {
663                    let mid = low + (high - low) / 2;
664                    if cum_freq < self.cdf_table[mid] {
665                        high = mid;
666                    } else {
667                        low = mid + 1;
668                    }
669                }
670                low
671            };
672            // upper_bound - 1 gives the last element ≤ cum_freq
673            let start_idx = upper_idx - 1;
674
675            let s0 = self.cdf_table[start_idx];
676            let s1 = self.cdf_table[start_idx + 1];
677            let freq = s1 - s0;
678
679            if !decoder.advance_symbol(&RansByteDecSymbol::new(s0, freq), self.symbol_bits) {
680                return Err(EntropyError::InvalidStream);
681            }
682
683            let mut symbol = (start_idx - base_offset) as i32;
684            if symbol == desc.bypass_sentinel {
685                let bypass_count = self.decode_bypass_count_byte(decoder)?;
686                let bypass_value = self.decode_bypass_value_payload_byte(decoder, bypass_count)?;
687                // Issue 5: safe conversion with overflow checks using i64
688                let half = (bypass_value >> 1) as i64;
689                if bypass_value & 1 != 0 {
690                    // Negative: 2*(-value) - 1 -> value = -(bypassValue >> 1) - 1
691                    // = -(half as i64) - 1
692                    symbol = (-half)
693                        .checked_sub(1)
694                        .ok_or(EntropyError::InvalidStream)?
695                        .try_into()
696                        .map_err(|_| EntropyError::InvalidStream)?;
697                } else {
698                    // Positive: 2*(value - sentinel) -> value = (bypassValue >> 1) + sentinel
699                    symbol = half
700                        .checked_add(desc.bypass_sentinel as i64)
701                        .ok_or(EntropyError::InvalidStream)?
702                        .try_into()
703                        .map_err(|_| EntropyError::InvalidStream)?;
704                }
705            }
706
707            values[i] = (symbol as i64)
708                .checked_sub(desc.value_offset as i64)
709                .ok_or(EntropyError::InvalidStream)?
710                .try_into()
711                .map_err(|_| EntropyError::InvalidStream)?;
712        }
713        Ok(())
714    }
715
716    fn decode_inner_64(
717        &self,
718        decoder: &mut msrtc_rans_core::Rans64Decoder<SliceSource<'_, u32>>,
719        values: &mut [i32],
720        indices: &[i32],
721    ) -> Result<(), EntropyError> {
722        if self.symbol_bits == 0 {
723            return Err(EntropyError::InvalidState);
724        }
725        if values.len() != indices.len() {
726            return Err(EntropyError::InvalidParams);
727        }
728
729        for (i, &index) in indices.iter().enumerate() {
730            if index < 0 {
731                values[i] = 0;
732                continue;
733            }
734
735            let dist_len = self.distribution_descs.len();
736            let ui = if (index as usize) < dist_len {
737                index as usize
738            } else {
739                dist_len - 1
740            };
741            let desc = &self.distribution_descs[ui];
742
743            let cum_freq = decoder.get(self.symbol_bits);
744            debug_assert!(cum_freq < (1u32 << self.symbol_bits));
745
746            let base_offset = desc.symbol_offset;
747            let lo = base_offset + 1;
748            let hi = base_offset + desc.bypass_sentinel as usize + 1;
749
750            let upper_idx = {
751                let mut low = lo;
752                let mut high = hi;
753                while low < high {
754                    let mid = low + (high - low) / 2;
755                    if cum_freq < self.cdf_table[mid] {
756                        high = mid;
757                    } else {
758                        low = mid + 1;
759                    }
760                }
761                low
762            };
763            let start_idx = upper_idx - 1;
764
765            let s0 = self.cdf_table[start_idx];
766            let s1 = self.cdf_table[start_idx + 1];
767            let freq = s1 - s0;
768
769            if !decoder.advance_symbol(&Rans64DecSymbol::new(s0, freq), self.symbol_bits) {
770                return Err(EntropyError::InvalidStream);
771            }
772
773            let mut symbol = (start_idx - base_offset) as i32;
774            if symbol == desc.bypass_sentinel {
775                let bypass_count = self.decode_bypass_count_64(decoder)?;
776                let bypass_value = self.decode_bypass_value_payload_64(decoder, bypass_count)?;
777                // Issue 5: safe conversion with overflow checks using i64
778                let half = (bypass_value >> 1) as i64;
779                if bypass_value & 1 != 0 {
780                    // Negative: 2*(-value) - 1 -> value = -(bypassValue >> 1) - 1
781                    // = -(half as i64) - 1
782                    symbol = (-half)
783                        .checked_sub(1)
784                        .ok_or(EntropyError::InvalidStream)?
785                        .try_into()
786                        .map_err(|_| EntropyError::InvalidStream)?;
787                } else {
788                    // Positive: 2*(value - sentinel) -> value = (bypassValue >> 1) + sentinel
789                    symbol = half
790                        .checked_add(desc.bypass_sentinel as i64)
791                        .ok_or(EntropyError::InvalidStream)?
792                        .try_into()
793                        .map_err(|_| EntropyError::InvalidStream)?;
794                }
795            }
796
797            values[i] = (symbol as i64)
798                .checked_sub(desc.value_offset as i64)
799                .ok_or(EntropyError::InvalidStream)?
800                .try_into()
801                .map_err(|_| EntropyError::InvalidStream)?;
802        }
803        Ok(())
804    }
805}
806
807// ---------------------------------------------------------------------------
808// Helper traits to map RansParams to encoder/decoder types
809// ---------------------------------------------------------------------------
810
811/// Maps `RansParams` implementations to their encoder symbol types.
812///
813/// This trait is automatically implemented for both `RansByte` and `Rans64`
814/// and should not need to be implemented manually.
815pub trait EncoderVariantForS: RansParams {
816    /// The encoder symbol type for this variant.
817    type EncSymbol: EncSymbol;
818
819    /// The raw rANS encoder type for this variant.
820    type RawEnc: RawEncoder<Symbol = Self::EncSymbol>;
821
822    /// Maximum scale bits for this variant.
823    const MAX_SCALE_BITS: u32;
824
825    /// Convert raw encoder units to a byte vector.
826    fn units_to_bytes(units: Vec<<Self::RawEnc as RawEncoder>::Unit>) -> Vec<u8>;
827
828    /// Create a new encoder instance.
829    fn make_encoder() -> Self::RawEnc;
830}
831
832impl EncoderVariantForS for RansByte {
833    type EncSymbol = RansByteEncSymbol;
834    type RawEnc = RansByteEncoder<VecSink<u8>>;
835    const MAX_SCALE_BITS: u32 = 30;
836    fn units_to_bytes(units: Vec<u8>) -> Vec<u8> {
837        units
838    }
839    fn make_encoder() -> Self::RawEnc {
840        RansByteEncoder::new(VecSink::new(4096))
841    }
842}
843
844impl EncoderVariantForS for Rans64 {
845    type EncSymbol = Rans64EncSymbol;
846    type RawEnc = Rans64Encoder<VecSink<u32>>;
847    const MAX_SCALE_BITS: u32 = 32;
848    fn units_to_bytes(units: Vec<u32>) -> Vec<u8> {
849        let mut bytes = Vec::with_capacity(units.len() * 4);
850        for &u in &units {
851            bytes.extend_from_slice(&u.to_le_bytes());
852        }
853        bytes
854    }
855    fn make_encoder() -> Self::RawEnc {
856        Rans64Encoder::new(VecSink::new(4096))
857    }
858}
859
860// ---------------------------------------------------------------------------
861// Public EntropyEncoder
862// ---------------------------------------------------------------------------
863
864/// High-level entropy encoder using PMF distributions with bypass support.
865///
866/// Generic over `S: RansParams` (`RansByte` or `Rans64`).
867///
868/// # Example
869///
870/// ```ignore
871/// use msrtc_rans::entropy::EntropyEncoder;
872/// use msrtc_rans::RansByte;
873///
874/// let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
875/// enc.initialize(
876///     &[4, 6],       // pmf_lengths
877///     &[1, 2],       // pmf_offsets
878///     &[1, 3, 1, 1, 1, 3, 5, 3, 1, 1],  // pmf_table
879///     16,            // symbol_bits
880///     4,             // bypass_bits
881/// ).unwrap();
882///
883/// let mut buffer = Vec::new();
884/// enc.encode(&[0, 1], &[1, 1], &mut buffer).unwrap();
885/// ```
886pub struct EntropyEncoder<S: EncoderVariantForS> {
887    state: EncoderState<<S as EncoderVariantForS>::EncSymbol>,
888}
889
890impl<S: EncoderVariantForS> EntropyEncoder<S> {
891    /// Create a new uninitialized entropy encoder.
892    pub fn new() -> Self {
893        Self {
894            state: EncoderState::uninitialized(),
895        }
896    }
897
898    /// Initialize the encoder with PMF distribution data.
899    ///
900    /// * `pmf_lengths` — number of symbols per distribution (including bypass sentinel)
901    /// * `pmf_offsets` — value offsets per distribution
902    /// * `pmf_table` — flat array of symbol frequencies for all distributions
903    /// * `symbol_bits` — number of bits for symbol encoding (e.g. 16)
904    /// * `bypass_bits` — number of bits for bypass encoding (e.g. 4)
905    pub fn initialize(
906        &mut self,
907        pmf_lengths: &[i32],
908        pmf_offsets: &[i32],
909        pmf_table: &[i32],
910        symbol_bits: u32,
911        bypass_bits: u32,
912    ) -> Result<(), EntropyError> {
913        self.state.initialize(
914            pmf_lengths,
915            pmf_offsets,
916            pmf_table,
917            symbol_bits as i32,
918            bypass_bits as i32,
919            <S as EncoderVariantForS>::MAX_SCALE_BITS,
920        )
921    }
922
923    /// One-shot encode: encode `indices`/`values` into `buffer`.
924    ///
925    /// The encoded bytes are appended to `buffer`.
926    pub fn encode(
927        &self,
928        indices: &[i32],
929        values: &[i32],
930        buffer: &mut Vec<u8>,
931    ) -> Result<(), EntropyError> {
932        let units = self.state.encode_to_vec(indices, values, S::make_encoder)?;
933        let bytes = S::units_to_bytes(units);
934        buffer.extend_from_slice(&bytes);
935        Ok(())
936    }
937}
938
939impl<S: EncoderVariantForS> Default for EntropyEncoder<S> {
940    fn default() -> Self {
941        Self::new()
942    }
943}
944
945fn _assert_encoder_bounds() {
946    fn _is_encoder<S: EncoderVariantForS>() {}
947    _is_encoder::<RansByte>();
948    _is_encoder::<Rans64>();
949}
950
951// ---------------------------------------------------------------------------
952// Public EntropyDecoder
953// ---------------------------------------------------------------------------
954
955/// High-level entropy decoder using CDF tables for symbol lookup.
956///
957/// Generic over `S: RansParams` (`RansByte` or `Rans64`).
958pub struct EntropyDecoder<S: RansParams> {
959    state: DecoderState,
960    _phantom: core::marker::PhantomData<S>,
961}
962
963impl<S: RansParams> EntropyDecoder<S> {
964    /// Create a new uninitialized entropy decoder.
965    pub fn new() -> Self {
966        Self {
967            state: DecoderState::uninitialized(),
968            _phantom: core::marker::PhantomData,
969        }
970    }
971
972    /// Initialize the decoder with PMF distribution data.
973    ///
974    /// * `pmf_lengths` — number of symbols per distribution (including bypass sentinel)
975    /// * `pmf_offsets` — value offsets per distribution
976    /// * `pmf_table` — flat array of symbol frequencies for all distributions
977    /// * `symbol_bits` — number of bits for symbol encoding (e.g. 16)
978    /// * `bypass_bits` — number of bits for bypass encoding (e.g. 4)
979    pub fn initialize(
980        &mut self,
981        pmf_lengths: &[i32],
982        pmf_offsets: &[i32],
983        pmf_table: &[i32],
984        symbol_bits: u32,
985        bypass_bits: u32,
986    ) -> Result<(), EntropyError> {
987        let max_scale_bits = match S::NAME {
988            "RansByte" => 30u32,
989            "Rans64" => 32u32,
990            _ => return Err(EntropyError::InvalidParams),
991        };
992        self.state.initialize(
993            pmf_lengths,
994            pmf_offsets,
995            pmf_table,
996            symbol_bits as i32,
997            bypass_bits as i32,
998            max_scale_bits,
999        )
1000    }
1001
1002    /// One-shot decode: decode from `data` into `values`.
1003    ///
1004    /// * `values` — output buffer (must be same length as `indices`)
1005    /// * `indices` — distribution indices for each value to decode
1006    /// * `data` — encoded byte stream
1007    pub fn decode(
1008        &self,
1009        values: &mut [i32],
1010        indices: &[i32],
1011        data: &[u8],
1012    ) -> Result<(), EntropyError> {
1013        let is_byte = match S::NAME {
1014            "RansByte" => true,
1015            "Rans64" => false,
1016            _ => return Err(EntropyError::InvalidParams),
1017        };
1018        self.state.decode_from_slice(values, indices, data, is_byte)
1019    }
1020}
1021
1022impl<S: RansParams> Default for EntropyDecoder<S> {
1023    fn default() -> Self {
1024        Self::new()
1025    }
1026}
1027
1028// ---------------------------------------------------------------------------
1029// Tests
1030// ---------------------------------------------------------------------------
1031
1032#[cfg(test)]
1033mod tests {
1034    use super::*;
1035
1036    // Reference test case from test_msrtc_rans.py:
1037    //   PMF_LENGTHS = [4, 6]
1038    //   PMF_OFFSETS = [1, 2]
1039    //   PMF_TABLE   = [1, 3, 1, 1, 1, 3, 5, 3, 1, 1]
1040    //   INDICES     = [0, 1, 0, 1]
1041    //   VALUES      = [-2, 1, 0, 1]
1042    //   SYMBOL_BITS = 16
1043    //   BYPASS_BITS = 4
1044    //
1045    // Reference bitstreams from upstream oracle (EntropyCoder.cpp):
1046    //   RansByte: hex = "0500bd040001a10003000b00"
1047    //   Rans64:   hex = "0500a1bd04000000110a002f03000300"
1048
1049    const PMF_LENGTHS: [i32; 2] = [4, 6];
1050    const PMF_OFFSETS: [i32; 2] = [1, 2];
1051    const PMF_TABLE: [i32; 10] = [1, 3, 1, 1, 1, 3, 5, 3, 1, 1];
1052    const INDICES: [i32; 4] = [0, 1, 0, 1];
1053    const VALUES: [i32; 4] = [-2, 1, 0, 1];
1054    const SYMBOL_BITS: u32 = 16;
1055    const BYPASS_BITS: u32 = 4;
1056
1057    const REF_HEX_BYTE: &str = "0500bd040001a10003000b00";
1058    const REF_HEX_64: &str = "0500a1bd04000000110a002f03000300";
1059
1060    fn hex_decode(hex: &str) -> Vec<u8> {
1061        (0..hex.len())
1062            .step_by(2)
1063            .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).unwrap())
1064            .collect()
1065    }
1066
1067    #[test]
1068    fn test_encoder_byte_initialize() {
1069        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1070        assert!(
1071            enc.initialize(
1072                &PMF_LENGTHS,
1073                &PMF_OFFSETS,
1074                &PMF_TABLE,
1075                SYMBOL_BITS,
1076                BYPASS_BITS
1077            )
1078            .is_ok()
1079        );
1080    }
1081
1082    #[test]
1083    fn test_encoder_64_initialize() {
1084        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1085        assert!(
1086            enc.initialize(
1087                &PMF_LENGTHS,
1088                &PMF_OFFSETS,
1089                &PMF_TABLE,
1090                SYMBOL_BITS,
1091                BYPASS_BITS
1092            )
1093            .is_ok()
1094        );
1095    }
1096
1097    #[test]
1098    fn test_encoder_rejects_invalid_pmf() {
1099        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1100        // Mismatched lengths/offsets
1101        assert_eq!(
1102            enc.initialize(&[4], &[1, 2], &PMF_TABLE, SYMBOL_BITS, BYPASS_BITS),
1103            Err(EntropyError::InvalidPmf)
1104        );
1105    }
1106
1107    #[test]
1108    fn test_encoder_rejects_invalid_params() {
1109        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1110        // symbol_bits < 2
1111        assert_eq!(
1112            enc.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, 1, BYPASS_BITS),
1113            Err(EntropyError::InvalidParams)
1114        );
1115    }
1116
1117    #[test]
1118    fn test_encoder_byte_rejects_length_leq_one() {
1119        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1120        // Length <= 1 is invalid (need tail mass for bypass)
1121        assert_eq!(
1122            enc.initialize(&[1, 6], &[1, 2], &PMF_TABLE, SYMBOL_BITS, BYPASS_BITS),
1123            Err(EntropyError::InvalidPmf)
1124        );
1125    }
1126
1127    #[test]
1128    fn test_encode_byte_matches_reference() {
1129        // Encodes values=[-2, 1, 0, 1] with RansByte.
1130        // Value -2 (index 0, offset 1 => adjusted=-1) triggers bypass.
1131        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1132        enc.initialize(
1133            &PMF_LENGTHS,
1134            &PMF_OFFSETS,
1135            &PMF_TABLE,
1136            SYMBOL_BITS,
1137            BYPASS_BITS,
1138        )
1139        .unwrap();
1140
1141        let mut buffer = Vec::new();
1142        enc.encode(&INDICES, &VALUES, &mut buffer).unwrap();
1143
1144        let expected = hex_decode(REF_HEX_BYTE);
1145        assert_eq!(
1146            buffer, expected,
1147            "RansByte encode output does not match reference hex"
1148        );
1149    }
1150
1151    #[test]
1152    fn test_encode_64_matches_reference() {
1153        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1154        enc.initialize(
1155            &PMF_LENGTHS,
1156            &PMF_OFFSETS,
1157            &PMF_TABLE,
1158            SYMBOL_BITS,
1159            BYPASS_BITS,
1160        )
1161        .unwrap();
1162
1163        let mut buffer = Vec::new();
1164        enc.encode(&INDICES, &VALUES, &mut buffer).unwrap();
1165
1166        let expected = hex_decode(REF_HEX_64);
1167        assert_eq!(
1168            buffer, expected,
1169            "Rans64 encode output does not match reference hex"
1170        );
1171    }
1172
1173    #[test]
1174    fn test_encode_in_range_values_no_bypass() {
1175        // Values that are all in-range (no bypass):
1176        // Dist 0: offset=1, sentinel=3, valid adjusted: [0,2] => value: [-1, 1]
1177        // Dist 1: offset=2, sentinel=5, valid adjusted: [0,4] => value: [-2, 2]
1178        let in_range_values = [1i32, 1, 0, 1];
1179        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1180        enc.initialize(
1181            &PMF_LENGTHS,
1182            &PMF_OFFSETS,
1183            &PMF_TABLE,
1184            SYMBOL_BITS,
1185            BYPASS_BITS,
1186        )
1187        .unwrap();
1188
1189        let mut buffer = Vec::new();
1190        let result = enc.encode(&INDICES, &in_range_values, &mut buffer);
1191        assert!(result.is_ok(), "encode should succeed: {:?}", result);
1192        assert!(!buffer.is_empty(), "encoded buffer should not be empty");
1193    }
1194
1195    #[test]
1196    fn test_decode_byte_roundtrip_in_range() {
1197        // Verify roundtrip encode-decode with in-range values (no bypass).
1198        let values = [1i32, 1, 0, 1];
1199
1200        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1201        enc.initialize(
1202            &PMF_LENGTHS,
1203            &PMF_OFFSETS,
1204            &PMF_TABLE,
1205            SYMBOL_BITS,
1206            BYPASS_BITS,
1207        )
1208        .unwrap();
1209
1210        let mut encoded = Vec::new();
1211        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1212
1213        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1214        dec.initialize(
1215            &PMF_LENGTHS,
1216            &PMF_OFFSETS,
1217            &PMF_TABLE,
1218            SYMBOL_BITS,
1219            BYPASS_BITS,
1220        )
1221        .unwrap();
1222
1223        let mut decoded = vec![0i32; values.len()];
1224        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1225
1226        assert_eq!(
1227            decoded, values,
1228            "roundtrip decode should match original values"
1229        );
1230    }
1231
1232    #[test]
1233    fn test_decode_64_roundtrip_in_range() {
1234        let values = [1i32, 1, 0, 1];
1235
1236        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1237        enc.initialize(
1238            &PMF_LENGTHS,
1239            &PMF_OFFSETS,
1240            &PMF_TABLE,
1241            SYMBOL_BITS,
1242            BYPASS_BITS,
1243        )
1244        .unwrap();
1245
1246        let mut encoded = Vec::new();
1247        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1248
1249        let mut dec: EntropyDecoder<Rans64> = EntropyDecoder::new();
1250        dec.initialize(
1251            &PMF_LENGTHS,
1252            &PMF_OFFSETS,
1253            &PMF_TABLE,
1254            SYMBOL_BITS,
1255            BYPASS_BITS,
1256        )
1257        .unwrap();
1258
1259        let mut decoded = vec![0i32; values.len()];
1260        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1261
1262        assert_eq!(
1263            decoded, values,
1264            "Rans64 roundtrip decode should match original values"
1265        );
1266    }
1267
1268    #[test]
1269    fn test_decode_byte_roundtrip_bypass() {
1270        // Roundtrip with values that require bypass (value=-2 is out-of-range).
1271        let values = [-2i32, 1, 0, 1];
1272
1273        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1274        enc.initialize(
1275            &PMF_LENGTHS,
1276            &PMF_OFFSETS,
1277            &PMF_TABLE,
1278            SYMBOL_BITS,
1279            BYPASS_BITS,
1280        )
1281        .unwrap();
1282
1283        let mut encoded = Vec::new();
1284        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1285
1286        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1287        dec.initialize(
1288            &PMF_LENGTHS,
1289            &PMF_OFFSETS,
1290            &PMF_TABLE,
1291            SYMBOL_BITS,
1292            BYPASS_BITS,
1293        )
1294        .unwrap();
1295
1296        let mut decoded = vec![0i32; values.len()];
1297        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1298
1299        assert_eq!(
1300            decoded, values,
1301            "bypass roundtrip decode should match original values"
1302        );
1303    }
1304
1305    #[test]
1306    fn test_decode_64_roundtrip_bypass() {
1307        let values = [-2i32, 1, 0, 1];
1308
1309        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1310        enc.initialize(
1311            &PMF_LENGTHS,
1312            &PMF_OFFSETS,
1313            &PMF_TABLE,
1314            SYMBOL_BITS,
1315            BYPASS_BITS,
1316        )
1317        .unwrap();
1318
1319        let mut encoded = Vec::new();
1320        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1321
1322        let mut dec: EntropyDecoder<Rans64> = EntropyDecoder::new();
1323        dec.initialize(
1324            &PMF_LENGTHS,
1325            &PMF_OFFSETS,
1326            &PMF_TABLE,
1327            SYMBOL_BITS,
1328            BYPASS_BITS,
1329        )
1330        .unwrap();
1331
1332        let mut decoded = vec![0i32; values.len()];
1333        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1334
1335        assert_eq!(
1336            decoded, values,
1337            "Rans64 bypass roundtrip decode should match original values"
1338        );
1339    }
1340
1341    // -----------------------------------------------------------------------
1342    // Issue 2d: scale-32 safe / reject tests
1343    // -----------------------------------------------------------------------
1344
1345    #[test]
1346    fn test_encoder_64_symbol_bits_31_accepted() {
1347        // Rans64 symbol_bits=31 is within max_safe_bits (31)
1348        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1349        assert!(
1350            enc.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, 31, BYPASS_BITS)
1351                .is_ok()
1352        );
1353    }
1354
1355    #[test]
1356    fn test_encoder_64_symbol_bits_32_rejected() {
1357        // Rans64 symbol_bits=32 exceeds max_safe_bits (31), must not panic
1358        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1359        assert_eq!(
1360            enc.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, 32, BYPASS_BITS),
1361            Err(EntropyError::InvalidParams)
1362        );
1363    }
1364
1365    #[test]
1366    fn test_encoder_64_bypass_bits_32_rejected() {
1367        // Rans64 bypass_bits=32 exceeds max_safe_bits (31), must not panic
1368        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1369        assert_eq!(
1370            enc.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, SYMBOL_BITS, 32),
1371            Err(EntropyError::InvalidParams)
1372        );
1373    }
1374
1375    // -----------------------------------------------------------------------
1376    // Issue 3: misaligned Rans64 streams rejected
1377    // -----------------------------------------------------------------------
1378
1379    #[test]
1380    fn test_decode_64_rejects_misaligned_1_extra_byte() {
1381        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1382        enc.initialize(
1383            &PMF_LENGTHS,
1384            &PMF_OFFSETS,
1385            &PMF_TABLE,
1386            SYMBOL_BITS,
1387            BYPASS_BITS,
1388        )
1389        .unwrap();
1390        let mut encoded = Vec::new();
1391        enc.encode(&INDICES, &[1i32, 1, 0, 1], &mut encoded)
1392            .unwrap();
1393
1394        // Append 1 extra byte to make it misaligned
1395        let mut misaligned = encoded.clone();
1396        misaligned.push(0xAB);
1397
1398        let mut dec: EntropyDecoder<Rans64> = EntropyDecoder::new();
1399        dec.initialize(
1400            &PMF_LENGTHS,
1401            &PMF_OFFSETS,
1402            &PMF_TABLE,
1403            SYMBOL_BITS,
1404            BYPASS_BITS,
1405        )
1406        .unwrap();
1407        let mut decoded = vec![0i32; 4];
1408        let result = dec.decode(&mut decoded, &INDICES, &misaligned);
1409        assert_eq!(result, Err(EntropyError::InvalidStream));
1410    }
1411
1412    #[test]
1413    fn test_decode_64_rejects_misaligned_2_extra_bytes() {
1414        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1415        enc.initialize(
1416            &PMF_LENGTHS,
1417            &PMF_OFFSETS,
1418            &PMF_TABLE,
1419            SYMBOL_BITS,
1420            BYPASS_BITS,
1421        )
1422        .unwrap();
1423        let mut encoded = Vec::new();
1424        enc.encode(&INDICES, &[1i32, 1, 0, 1], &mut encoded)
1425            .unwrap();
1426
1427        let mut misaligned = encoded.clone();
1428        misaligned.extend_from_slice(&[0xAB, 0xCD]);
1429
1430        let mut dec: EntropyDecoder<Rans64> = EntropyDecoder::new();
1431        dec.initialize(
1432            &PMF_LENGTHS,
1433            &PMF_OFFSETS,
1434            &PMF_TABLE,
1435            SYMBOL_BITS,
1436            BYPASS_BITS,
1437        )
1438        .unwrap();
1439        let mut decoded = vec![0i32; 4];
1440        let result = dec.decode(&mut decoded, &INDICES, &misaligned);
1441        assert_eq!(result, Err(EntropyError::InvalidStream));
1442    }
1443
1444    #[test]
1445    fn test_decode_64_rejects_misaligned_3_extra_bytes() {
1446        let mut enc: EntropyEncoder<Rans64> = EntropyEncoder::new();
1447        enc.initialize(
1448            &PMF_LENGTHS,
1449            &PMF_OFFSETS,
1450            &PMF_TABLE,
1451            SYMBOL_BITS,
1452            BYPASS_BITS,
1453        )
1454        .unwrap();
1455        let mut encoded = Vec::new();
1456        enc.encode(&INDICES, &[1i32, 1, 0, 1], &mut encoded)
1457            .unwrap();
1458
1459        let mut misaligned = encoded.clone();
1460        misaligned.extend_from_slice(&[0xAB, 0xCD, 0xEF]);
1461
1462        let mut dec: EntropyDecoder<Rans64> = EntropyDecoder::new();
1463        dec.initialize(
1464            &PMF_LENGTHS,
1465            &PMF_OFFSETS,
1466            &PMF_TABLE,
1467            SYMBOL_BITS,
1468            BYPASS_BITS,
1469        )
1470        .unwrap();
1471        let mut decoded = vec![0i32; 4];
1472        let result = dec.decode(&mut decoded, &INDICES, &misaligned);
1473        assert_eq!(result, Err(EntropyError::InvalidStream));
1474    }
1475
1476    #[test]
1477    fn test_decode_byte_accepts_extra_bytes() {
1478        // RansByte has byte-level alignment, extra bytes should not be rejected
1479        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1480        enc.initialize(
1481            &PMF_LENGTHS,
1482            &PMF_OFFSETS,
1483            &PMF_TABLE,
1484            SYMBOL_BITS,
1485            BYPASS_BITS,
1486        )
1487        .unwrap();
1488        let mut encoded = Vec::new();
1489        enc.encode(&INDICES, &[1i32, 1, 0, 1], &mut encoded)
1490            .unwrap();
1491
1492        // Append extra bytes
1493        let mut extended = encoded.clone();
1494        extended.extend_from_slice(&[0xAB, 0xCD]);
1495
1496        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1497        dec.initialize(
1498            &PMF_LENGTHS,
1499            &PMF_OFFSETS,
1500            &PMF_TABLE,
1501            SYMBOL_BITS,
1502            BYPASS_BITS,
1503        )
1504        .unwrap();
1505        let mut decoded = vec![0i32; 4];
1506        // This may fail because the decoder checks EOF, but it should NOT
1507        // be rejected for misalignment
1508        let _ = dec.decode(&mut decoded, &INDICES, &extended);
1509        // We don't assert success or failure — we just assert no panic
1510    }
1511
1512    // -----------------------------------------------------------------------
1513    // Issue 4: Expanded bypass coverage
1514    // -----------------------------------------------------------------------
1515
1516    #[test]
1517    fn test_encode_bypass_positive_outlier() {
1518        // Value > sentinel (positive outlier): dist 0 sentinel=3, offset=1,
1519        // value=10 => adjusted=11 > 3 => bypass (8/2=4 above sentinel => value 4+3=7-1=6...
1520        // actually: adjusted=11, sentinel=3, bypass_value = 2*(11-3) = 16
1521        // decode: 16>>1=8, 8+3=11-1=10 ✓
1522        let values = [10i32, 1, 0, 1];
1523        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1524        enc.initialize(
1525            &PMF_LENGTHS,
1526            &PMF_OFFSETS,
1527            &PMF_TABLE,
1528            SYMBOL_BITS,
1529            BYPASS_BITS,
1530        )
1531        .unwrap();
1532        let mut encoded = Vec::new();
1533        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1534
1535        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1536        dec.initialize(
1537            &PMF_LENGTHS,
1538            &PMF_OFFSETS,
1539            &PMF_TABLE,
1540            SYMBOL_BITS,
1541            BYPASS_BITS,
1542        )
1543        .unwrap();
1544        let mut decoded = vec![0i32; 4];
1545        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1546        assert_eq!(decoded, values);
1547    }
1548
1549    #[test]
1550    fn test_encode_bypass_multi_digit_value() {
1551        // Value requiring multiple bypassBits-sized chunks (bypass_bits=4)
1552        // Large bypass value: dist 0 sentinel=3, offset=1, value=200 => adjusted=201
1553        // bypass_value = 2*(201-3) = 396 = 0x18C, needs multiple 4-bit chunks
1554        let values = [200i32, 1, 0, 1];
1555        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1556        enc.initialize(
1557            &PMF_LENGTHS,
1558            &PMF_OFFSETS,
1559            &PMF_TABLE,
1560            SYMBOL_BITS,
1561            BYPASS_BITS,
1562        )
1563        .unwrap();
1564        let mut encoded = Vec::new();
1565        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1566
1567        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1568        dec.initialize(
1569            &PMF_LENGTHS,
1570            &PMF_OFFSETS,
1571            &PMF_TABLE,
1572            SYMBOL_BITS,
1573            BYPASS_BITS,
1574        )
1575        .unwrap();
1576        let mut decoded = vec![0i32; 4];
1577        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1578        assert_eq!(decoded, values);
1579    }
1580
1581    #[test]
1582    fn test_encode_bypass_bits_2() {
1583        // Minimum bypass_bits = 2
1584        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1585        enc.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, SYMBOL_BITS, 2)
1586            .unwrap();
1587        let values = [10i32, 1, 0, 1]; // value 10 => bypass
1588        let mut encoded = Vec::new();
1589        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1590
1591        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1592        dec.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, SYMBOL_BITS, 2)
1593            .unwrap();
1594        let mut decoded = vec![0i32; 4];
1595        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1596        assert_eq!(decoded, values);
1597    }
1598
1599    #[test]
1600    fn test_encode_bypass_bits_3() {
1601        // Odd bypass_bits = 3
1602        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1603        enc.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, SYMBOL_BITS, 3)
1604            .unwrap();
1605        let values = [10i32, 1, 0, 1];
1606        let mut encoded = Vec::new();
1607        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1608
1609        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1610        dec.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, SYMBOL_BITS, 3)
1611            .unwrap();
1612        let mut decoded = vec![0i32; 4];
1613        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1614        assert_eq!(decoded, values);
1615    }
1616
1617    #[test]
1618    fn test_encode_bypass_bits_8() {
1619        // Larger bypass_bits = 8
1620        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1621        enc.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, SYMBOL_BITS, 8)
1622            .unwrap();
1623        let values = [10i32, 1, 0, 1];
1624        let mut encoded = Vec::new();
1625        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1626
1627        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1628        dec.initialize(&PMF_LENGTHS, &PMF_OFFSETS, &PMF_TABLE, SYMBOL_BITS, 8)
1629            .unwrap();
1630        let mut decoded = vec![0i32; 4];
1631        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1632        assert_eq!(decoded, values);
1633    }
1634
1635    #[test]
1636    fn test_encode_bypass_multiple_bypasses() {
1637        // Multiple bypass values in one stream: both -2 and 10 need bypass
1638        // dist 0: offset=1 sentinel=3, dist 1: offset=2 sentinel=5
1639        // value -2 (dist 0) => adjusted=-1 => bypass (negative)
1640        // value 10 (dist 1) => adjusted=12 => bypass (positive)
1641        let values = [-2i32, 10, 0, 1];
1642        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1643        enc.initialize(
1644            &PMF_LENGTHS,
1645            &PMF_OFFSETS,
1646            &PMF_TABLE,
1647            SYMBOL_BITS,
1648            BYPASS_BITS,
1649        )
1650        .unwrap();
1651        let mut encoded = Vec::new();
1652        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1653
1654        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1655        dec.initialize(
1656            &PMF_LENGTHS,
1657            &PMF_OFFSETS,
1658            &PMF_TABLE,
1659            SYMBOL_BITS,
1660            BYPASS_BITS,
1661        )
1662        .unwrap();
1663        let mut decoded = vec![0i32; 4];
1664        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1665        assert_eq!(decoded, values);
1666    }
1667
1668    #[test]
1669    fn test_encode_bypass_mixed_in_range_and_bypass() {
1670        // Mix of in-range and bypass values
1671        // dist 0: offset=1 sentinel=3, valid adjusted [0,2] => values [-1, 1]
1672        // dist 1: offset=2 sentinel=5, valid adjusted [0,4] => values [-2, 2]
1673        // value 0 in dist 0 => in-range, value 1 in dist 0 => in-range
1674        // value 5 in dist 1 => bypass (adjusted=7 > 4), value -3 in dist 1 => bypass (adjusted=-1 < 0)
1675        let values = [0i32, 5, 1, -3];
1676        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1677        enc.initialize(
1678            &PMF_LENGTHS,
1679            &PMF_OFFSETS,
1680            &PMF_TABLE,
1681            SYMBOL_BITS,
1682            BYPASS_BITS,
1683        )
1684        .unwrap();
1685        let mut encoded = Vec::new();
1686        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1687
1688        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1689        dec.initialize(
1690            &PMF_LENGTHS,
1691            &PMF_OFFSETS,
1692            &PMF_TABLE,
1693            SYMBOL_BITS,
1694            BYPASS_BITS,
1695        )
1696        .unwrap();
1697        let mut decoded = vec![0i32; 4];
1698        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1699        assert_eq!(decoded, values);
1700    }
1701
1702    #[test]
1703    fn test_encode_bypass_negative_outlier_at_boundary() {
1704        // Negative outlier at boundary: -1 - sentinel (very negative)
1705        // dist 0: offset=1, sentinel=3, value=-10 => adjusted=-9 => bypass
1706        // (-9 < 0) => bypass_value = 2*9-1 = 17, decode: 17>>1=8, -(8+1) = -9, -9+1 = -8... wait
1707        // decode bypass: negative flag set, half=8, symbol = -(8+1) = -9, -9 = -9+1 = -8...
1708        // Actually: symbol = -9, values[i] = symbol - offset = (-9) - 1 = -10 ✓
1709        let values = [-10i32, 1, 0, 1];
1710        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1711        enc.initialize(
1712            &PMF_LENGTHS,
1713            &PMF_OFFSETS,
1714            &PMF_TABLE,
1715            SYMBOL_BITS,
1716            BYPASS_BITS,
1717        )
1718        .unwrap();
1719        let mut encoded = Vec::new();
1720        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1721
1722        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1723        dec.initialize(
1724            &PMF_LENGTHS,
1725            &PMF_OFFSETS,
1726            &PMF_TABLE,
1727            SYMBOL_BITS,
1728            BYPASS_BITS,
1729        )
1730        .unwrap();
1731        let mut decoded = vec![0i32; 4];
1732        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1733        assert_eq!(decoded, values);
1734    }
1735
1736    #[test]
1737    fn test_encode_bypass_large_positive_outlier() {
1738        // Large positive outlier
1739        let values = [10000i32, 1, 0, 1];
1740        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1741        enc.initialize(
1742            &PMF_LENGTHS,
1743            &PMF_OFFSETS,
1744            &PMF_TABLE,
1745            SYMBOL_BITS,
1746            BYPASS_BITS,
1747        )
1748        .unwrap();
1749        let mut encoded = Vec::new();
1750        enc.encode(&INDICES, &values, &mut encoded).unwrap();
1751
1752        let mut dec: EntropyDecoder<RansByte> = EntropyDecoder::new();
1753        dec.initialize(
1754            &PMF_LENGTHS,
1755            &PMF_OFFSETS,
1756            &PMF_TABLE,
1757            SYMBOL_BITS,
1758            BYPASS_BITS,
1759        )
1760        .unwrap();
1761        let mut decoded = vec![0i32; 4];
1762        dec.decode(&mut decoded, &INDICES, &encoded).unwrap();
1763        assert_eq!(decoded, values);
1764    }
1765
1766    // -----------------------------------------------------------------------
1767    // Issue 5: extreme value overflow protection
1768    // -----------------------------------------------------------------------
1769
1770    #[test]
1771    fn test_encode_bypass_extreme_negative_i32_min_plus_one() {
1772        // i32::MIN + 1 with offset 1 gives adjusted = i32::MIN + 2 = -2147483646
1773        // checked_neg of that gives 2147483646, no overflow.
1774        // This should succeed (no overflow).
1775        let values = [i32::MIN + 1, 1, 0, 1];
1776        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1777        enc.initialize(
1778            &PMF_LENGTHS,
1779            &PMF_OFFSETS,
1780            &PMF_TABLE,
1781            SYMBOL_BITS,
1782            BYPASS_BITS,
1783        )
1784        .unwrap();
1785        let mut encoded = Vec::new();
1786        let result = enc.encode(&INDICES, &values, &mut encoded);
1787        // Must not panic — should succeed or return InvalidParams gracefully
1788        assert!(result.is_ok() || result == Err(EntropyError::InvalidParams));
1789    }
1790
1791    #[test]
1792    fn test_encode_bypass_extreme_positive_i32_max() {
1793        // i32::MAX with offset could cause overflow in checked_add -> InvalidParams
1794        let values = [i32::MAX, 1, 0, 1];
1795        let mut enc: EntropyEncoder<RansByte> = EntropyEncoder::new();
1796        enc.initialize(
1797            &PMF_LENGTHS,
1798            &PMF_OFFSETS,
1799            &PMF_TABLE,
1800            SYMBOL_BITS,
1801            BYPASS_BITS,
1802        )
1803        .unwrap();
1804        let mut encoded = Vec::new();
1805        let result = enc.encode(&INDICES, &values, &mut encoded);
1806        assert_eq!(result, Err(EntropyError::InvalidParams));
1807    }
1808}