Skip to main content

oxideav_opus/
range_decoder.rs

1//! Range decoder primitives for the Opus codec.
2//!
3//! This module implements the bit-exact range decoder described in
4//! RFC 6716 §4.1 (`docs/audio/opus/rfc6716-opus.txt`). The implementation
5//! is clean-room: every routine is transcribed from the prose and
6//! pseudocode equations in the RFC; no external library source was
7//! consulted.
8//!
9//! The range decoder is the SHARED entropy primitive that both the SILK
10//! and CELT layers of Opus invoke for every coded symbol. The
11//! [`oxideav-celt`] crate carries its own copy of the same primitive;
12//! each crate owns its copy until a shared low-level primitive crate
13//! exists in the workspace. The two copies are independent clean-room
14//! transcriptions of the same RFC sections and are expected to be
15//! behaviourally identical.
16//!
17//! The following routines are wired up:
18//!
19//! * Initialization (§4.1.1).
20//! * Symbol-update internal helper (§4.1.2).
21//! * Renormalization (§4.1.2.1).
22//! * [`RangeDecoder::decode_bin`] for power-of-two `ft` symbols (§4.1.3.1).
23//! * [`RangeDecoder::dec_bit_logp`] (§4.1.3.2).
24//! * [`RangeDecoder::dec_icdf`] for inverse-CDF table decoding (§4.1.3.3).
25//! * [`RangeDecoder::dec_bits`] for raw bits (§4.1.4).
26//! * [`RangeDecoder::dec_uint`] for uniformly-distributed integers
27//!   (§4.1.5).
28//! * [`RangeDecoder::tell`] for whole-bit accounting (§4.1.6.1).
29//! * [`RangeDecoder::tell_frac`] for 1/8th-bit-precision accounting
30//!   (§4.1.6.2).
31//! * [`RangeDecoder::ec_decode`] / [`RangeDecoder::ec_dec_update`] for
32//!   the generic two-step symbol path (§4.1.2). These are the building
33//!   blocks for custom symbol decoders that an inverse-CDF table cannot
34//!   express directly — notably the CELT §4.3.2.1 coarse-energy
35//!   Laplace decoder and the §4.3.3 allocation interpolation search,
36//!   both of which decode against a frequency model computed at
37//!   run time rather than a fixed `icdf[]` table.
38
39use crate::Error;
40
41/// Bit-exact CELT/SILK range decoder state per RFC 6716 §4.1.
42///
43/// The decoder splits the input buffer into two halves. The range
44/// coder consumes bytes from the front (MSB-first into the range
45/// state) and the raw-bit reader consumes bytes from the back
46/// (LSB-first). RFC 6716 §4.1.4 explicitly permits the two readers
47/// to overlap; the decoder MUST allow it.
48#[derive(Debug)]
49pub struct RangeDecoder<'a> {
50    /// Input bitstream backing this decoder.
51    buf: &'a [u8],
52    /// Offset of the next byte the range coder will consume (advances
53    /// forward through `buf`).
54    fwd: usize,
55    /// Number of bytes consumed by the raw-bit reader, measured from
56    /// the END of `buf`. A value of `0` means no raw bit has yet been
57    /// read; the next raw byte fetched comes from `buf[buf.len() - 1]`.
58    back: usize,
59    /// Number of unconsumed bits currently sitting in `back_window`
60    /// (0..=8 at rest, may exceed during refill).
61    back_bits_avail: u32,
62    /// Buffer of unconsumed raw bits, packed with the next bit to
63    /// emit in bit 0.
64    back_window: u32,
65    /// One-bit buffer holding the LSB of the previously-consumed
66    /// forward byte (used in the next renormalization step, §4.1.2.1).
67    rem: u32,
68    /// Range size; the renormalization invariant is `rng > 2**23`.
69    rng: u32,
70    /// Top of range minus current code value, minus one.
71    val: u32,
72    /// Running tally of whole bits the range coder has consumed
73    /// (RFC 6716 §4.1.6 `nbits_total`).
74    nbits_total: u32,
75    /// Number of raw bits the decoder has read so far. RFC 6716 §4.1.6
76    /// adds these into the bit-usage accounting on top of `nbits_total`.
77    nbits_raw: u32,
78    /// Sticky error flag: any decode that detects a corrupt frame
79    /// latches an error. Once set, subsequent decodes return zeroes
80    /// rather than corrupting the caller's state. RFC 6716 §4.1.5
81    /// recommends this behaviour for malformed integer decodes.
82    error: bool,
83}
84
85impl<'a> RangeDecoder<'a> {
86    /// Renormalization invariant from §4.1.2.1: `rng > 2**23`.
87    const RNG_MIN: u32 = 1 << 23;
88
89    /// Initialize the range decoder over `buf` per RFC 6716 §4.1.1.
90    ///
91    /// The spec defines `b0` as "the first input byte (or zero if
92    /// there are no bytes in this Opus frame)". The decoder sets
93    /// `rng = 128`, `val = 127 - (b0 >> 1)`, buffers the leftover bit
94    /// `(b0 & 1)`, then immediately invokes renormalization so the
95    /// invariant `rng > 2**23` holds before any symbol is decoded.
96    pub fn new(buf: &'a [u8]) -> Self {
97        let b0 = buf.first().copied().unwrap_or(0) as u32;
98        let mut dec = Self {
99            buf,
100            // §4.1.1: the first byte is consumed by initialization,
101            // so the next forward fetch starts at index 1.
102            fwd: if buf.is_empty() { 0 } else { 1 },
103            back: 0,
104            back_bits_avail: 0,
105            back_window: 0,
106            rem: b0 & 1,
107            rng: 128,
108            val: 127 - (b0 >> 1),
109            // §4.1.6: "nbits_total is initialized to 9 just before the
110            // initial range renormalization process completes."
111            nbits_total: 9,
112            nbits_raw: 0,
113            error: false,
114        };
115        dec.normalize();
116        dec
117    }
118
119    /// Whether this decoder has latched a `frame corrupt` error
120    /// somewhere in its history. Higher-level decoders use this to
121    /// abort the current frame and apply packet-loss concealment.
122    pub fn has_error(&self) -> bool {
123        self.error
124    }
125
126    /// Current whole-bit budget consumed by the range coder plus the
127    /// raw-bit reader, per RFC 6716 §4.1.6.1.
128    ///
129    /// `ec_tell` is defined as `nbits_total - ilog(rng)`. Raw bits are
130    /// added separately because §4.1.6 specifies that raw bits also
131    /// count against the total.
132    pub fn tell(&self) -> u32 {
133        // `ilog(rng)` is the position of the most-significant set bit
134        // of `rng`, counting from 1. The renormalization invariant
135        // keeps `rng >= 2**23`, so `lg` is always at least 24.
136        let lg = 32 - self.rng.leading_zeros();
137        self.nbits_total
138            .saturating_sub(lg)
139            .saturating_add(self.nbits_raw)
140    }
141
142    /// Current 1/8th-bit-precision budget consumed by the range coder
143    /// plus the raw-bit reader, per RFC 6716 §4.1.6.2.
144    ///
145    /// Follows §4.1.6.2 directly: from `lg = ilog(rng)`, extract
146    /// `r_Q15 = rng >> (lg - 16)` as a Q15 value in `[2^15, 2^16)`.
147    /// Three iterations of
148    /// `r_Q15 = (r_Q15*r_Q15) >> 15; lg = 2*lg + (r_Q15 >> 16)` extend
149    /// `lg` to 1/8th-bit precision. Raw bits add `8*nbits_raw` (whole
150    /// bits scaled into eighths). By construction,
151    /// `ec_tell() == ceil(ec_tell_frac() / 8.0)`.
152    pub fn tell_frac(&self) -> u32 {
153        let lg0 = 32 - self.rng.leading_zeros();
154        // §4.1.6.2: lg >= 24 after renormalization, so the shift below
155        // is well-defined.  r_Q15 in [2^15, 2^16).
156        let mut r_q15 = self.rng >> (lg0 - 16);
157        // Build the 1/8th-bit-precision lg one bit at a time. The
158        // spec doubles `lg` on each of the three refinement passes;
159        // the accumulator starts at the whole-bit value `lg0`.
160        let mut lg_frac = lg0;
161        // Three passes yield three extra bits = 1/8th-bit precision.
162        for _ in 0..3 {
163            r_q15 = (r_q15 * r_q15) >> 15;
164            let bit = r_q15 >> 16;
165            lg_frac = 2 * lg_frac + bit;
166            // If `bit == 1`, halve r_Q15 so it falls back into
167            // [2^15, 2^16).
168            if bit == 1 {
169                r_q15 >>= 1;
170            }
171        }
172        // Final value = nbits_total*8 - lg_frac + nbits_raw*8.
173        self.nbits_total
174            .saturating_mul(8)
175            .saturating_sub(lg_frac)
176            .saturating_add(self.nbits_raw.saturating_mul(8))
177    }
178
179    /// Decode a single binary symbol with probability `2^-logp` of
180    /// being a "1", per RFC 6716 §4.1.3.2.
181    ///
182    /// Mathematically equivalent to `ec_decode(ft = 1<<logp)` followed
183    /// by `ec_dec_update(0, ft-1, ft)` (for a "0") or
184    /// `ec_dec_update(ft-1, ft, ft)` (for a "1"). The implementation
185    /// is multiply-and-divide-free: `r >> logp` replaces `rng/ft`, and
186    /// the discriminator collapses to a comparison.
187    pub fn dec_bit_logp(&mut self, logp: u32) -> u32 {
188        let r = self.rng;
189        let d = self.val;
190        // `s = r >> logp` corresponds to `rng/ft` with `ft = 1<<logp`
191        // (an exact shift when ft is a power of two).
192        let s = r >> logp;
193        // The "1" half corresponds to `fl = ft-1, fh = ft`, leading to
194        //   val unchanged, rng = s.
195        // The "0" half is `fl = 0, fh = ft-1`, leading to
196        //   val -= s, rng = r - s.
197        let bit = if d < s { 1 } else { 0 };
198        if bit == 1 {
199            self.rng = s;
200        } else {
201            self.val = d - s;
202            self.rng = r - s;
203        }
204        self.normalize();
205        bit
206    }
207
208    /// Decode `bits` raw bits per RFC 6716 §4.1.4.
209    ///
210    /// Raw bits are packed at the END of the frame: the least
211    /// significant bit of the first value is the LSB of the last
212    /// byte; reads proceed toward the front. The function returns the
213    /// raw bits in the order written — the LSB of the result holds
214    /// the bit the encoder emitted first.
215    ///
216    /// Returns `0` on errors (`bits > 32`); also returns zero-extended
217    /// bits past the end of the frame, matching §4.1.4's "the decoder
218    /// MUST continue to use zero for any further input bytes required".
219    pub fn dec_bits(&mut self, bits: u32) -> u32 {
220        if bits == 0 {
221            return 0;
222        }
223        if bits > 32 {
224            self.error = true;
225            return 0;
226        }
227        // Work in a 64-bit window: serving a full 32-bit read may hold
228        // up to 39 bits in flight (7 residual + 4 fresh bytes), and the
229        // final `>> bits` must be defined for `bits == 32` (a round-382
230        // fuzz find: the previous u32 window overflowed both the refill
231        // shift and the consume shift on a 32-bit read).
232        let mut window = self.back_window as u64;
233        let mut avail = self.back_bits_avail;
234        // Refill the window until it holds enough bits to service the
235        // requested read.
236        while avail < bits {
237            let byte = if self.back < self.buf.len() {
238                self.buf[self.buf.len() - 1 - self.back]
239            } else {
240                // §4.1.4: zero-extend past the end of the frame.
241                0
242            };
243            self.back = self.back.saturating_add(1);
244            // Concatenate the new byte ABOVE the existing window so the
245            // intra-byte LSB-first packing is preserved.
246            window |= (byte as u64) << avail;
247            avail += 8;
248        }
249        let mask: u64 = if bits >= 32 {
250            0xFFFF_FFFF
251        } else {
252            (1u64 << bits) - 1
253        };
254        let result = (window & mask) as u32;
255        // Consume the served bits; fewer than 8 bits remain after any
256        // serve, so the truncation back to the u32 field is lossless.
257        self.back_window = (window >> bits) as u32;
258        self.back_bits_avail = avail - bits;
259        self.nbits_raw += bits;
260        result
261    }
262
263    /// Decode one of `ft` equiprobable values in `0..ft`, per
264    /// RFC 6716 §4.1.5.
265    ///
266    /// Values of `ft <= 1` degenerate to the constant `0`. `ft` may
267    /// be as large as `2^32 - 1`. The §4.1.5 procedure splits the
268    /// value: the top 8 bits go through the range coder, the
269    /// remainder through raw bits. If the reconstructed value is
270    /// `>= ft`, the frame is corrupt — the decoder latches the error
271    /// flag and saturates to `ft - 1` per §4.1.5's concealment
272    /// recommendation.
273    pub fn dec_uint(&mut self, ft: u32) -> Result<u32, Error> {
274        if ft <= 1 {
275            return Ok(0);
276        }
277        // `ftb = ilog(ft - 1)`: number of bits needed for `ft - 1`.
278        let ftb = 32 - (ft - 1).leading_zeros();
279        if ftb <= 8 {
280            // Small case: a single range-coded symbol covers the whole
281            // value.
282            let t = self.decode(ft);
283            self.dec_update(t, t + 1, ft);
284            Ok(t)
285        } else {
286            // Large case: top 8 bits range-coded, remainder raw.
287            let split_bits = ftb - 8;
288            let top_ft = ((ft - 1) >> split_bits) + 1;
289            let t_hi = self.decode(top_ft);
290            self.dec_update(t_hi, t_hi + 1, top_ft);
291            let t_lo = self.dec_bits(split_bits);
292            let t = (t_hi << split_bits) | t_lo;
293            if t >= ft {
294                self.error = true;
295                Ok(ft - 1)
296            } else {
297                Ok(t)
298            }
299        }
300    }
301
302    /// Decode `fs` for a power-of-two `ft = 1<<ftb` per RFC 6716
303    /// §4.1.3.1 (`ec_decode_bin`).
304    ///
305    /// Mathematically equivalent to [`Self::decode`] with `ft = 1<<ftb`
306    /// but avoids the division: `rng / ft == rng >> ftb`. The caller is
307    /// expected to follow with [`Self::dec_update`] (or use
308    /// [`Self::dec_icdf`] which fuses the two steps).
309    ///
310    /// Returns `fs` in the range `[0, 1<<ftb)`.
311    pub fn decode_bin(&mut self, ftb: u32) -> u32 {
312        let s = self.rng >> ftb;
313        if s == 0 {
314            // Would only happen for ftb > ilog(rng). The
315            // renormalization invariant keeps ilog(rng) >= 24, so any
316            // practical ftb (icdf uses up to 8) is safe. Defensively
317            // saturate to 0.
318            return 0;
319        }
320        let ft = 1u32 << ftb;
321        let approx = (self.val / s).saturating_add(1);
322        ft - approx.min(ft)
323    }
324
325    /// Decode a symbol via an inverse-CDF table, per RFC 6716 §4.1.3.3
326    /// (`ec_dec_icdf`).
327    ///
328    /// `icdf[k]` stores `(1<<ftb) - fh[k]`, terminated by a `0` entry
329    /// (the implicit `fh[K_last] == ft`). `fl[0]` is implicitly 0; the
330    /// table values are strictly monotonically decreasing.
331    ///
332    /// Fuses the search step (find the smallest `k` such that
333    /// `fs < ft - icdf[k]`) with the range/value update, eliminating
334    /// the division. The renormalization loop runs before returning.
335    ///
336    /// Returns the decoded symbol index `k` in `0..icdf.len()-1`. On a
337    /// malformed table (no terminating zero), the decoder latches its
338    /// sticky error flag and returns 0.
339    pub fn dec_icdf(&mut self, icdf: &[u8], ftb: u32) -> u32 {
340        // `s` corresponds to `rng / ft` for `ft = 1<<ftb`.
341        let s = self.rng >> ftb;
342        // Forward walk: for each candidate k, compute
343        //   next = s * icdf[k]
344        // which is the "remaining range above this symbol". The first
345        // k where `val >= next` is the decoded symbol. `t` tracks the
346        // previous step's `next` so that `rng' = t - next` matches the
347        // §4.1.2 update for `fl[k] == prev_next/s` and `fh[k] ==
348        // next/s` (with k=0 falling out to `rng - s*icdf[0]` since
349        // `t` starts at `rng`).
350        let mut t = self.rng;
351        for (k, &cell) in icdf.iter().enumerate() {
352            let next = s.saturating_mul(cell as u32);
353            if self.val >= next {
354                self.val -= next;
355                self.rng = t - next;
356                self.normalize();
357                return k as u32;
358            }
359            t = next;
360        }
361        // Malformed table: no terminator reached. §4.1.5 advises
362        // latching the corrupt-frame error and returning a saturated
363        // value.
364        self.error = true;
365        0
366    }
367
368    /// `ec_decode(ft)` per RFC 6716 §4.1.2 — the first of the two
369    /// symbol-decode steps.
370    ///
371    /// Computes the 16-bit symbol proxy
372    /// `fs = ft - min(val / (rng / ft) + 1, ft)`, which "lies within
373    /// the range of some symbol in the current context". The caller
374    /// then identifies the symbol `k` whose three-tuple
375    /// `(fl[k], fh[k], ft)` satisfies `fl[k] <= fs < fh[k]` and feeds
376    /// that tuple to [`Self::ec_dec_update`].
377    ///
378    /// This split form is needed when the frequency model is computed
379    /// at run time and cannot be pre-baked into a static inverse-CDF
380    /// table (RFC 6716 §4.3.2.1 coarse-energy Laplace decode, §4.3.3
381    /// allocation search). For fixed PDFs prefer [`Self::dec_icdf`],
382    /// which fuses both steps and avoids a division.
383    ///
384    /// `ft` must be in `1..=2**16` for the §4.1.2 derivation to hold
385    /// (the renormalization invariant keeps `rng > 2**23`, so
386    /// `rng / ft >= 1`). `ft == 0` would divide by zero; the decoder
387    /// latches its sticky error flag and returns `0` instead. The
388    /// returned `fs` lies in `[0, ft)`.
389    pub fn ec_decode(&mut self, ft: u32) -> u32 {
390        if ft == 0 {
391            self.error = true;
392            return 0;
393        }
394        self.decode(ft)
395    }
396
397    /// `ec_dec_update(fl, fh, ft)` per RFC 6716 §4.1.2 — the second of
398    /// the two symbol-decode steps.
399    ///
400    /// Narrows the range to the chosen symbol's `[fl, fh)` sub-interval
401    /// of `[0, ft)` per the §4.1.2 update equations, then renormalizes
402    /// to restore `rng > 2**23`. Pair this with the index returned by
403    /// the caller's search over the value from [`Self::ec_decode`].
404    ///
405    /// The three-tuple MUST satisfy `0 <= fl < fh <= ft` and
406    /// `1 <= ft <= 2**16`. A malformed tuple (`ft == 0`, `fh > ft`, or
407    /// `fl >= fh`) cannot come from a well-formed search; the decoder
408    /// latches its sticky error flag and leaves its state unchanged
409    /// rather than underflowing `val` or zeroing `rng`.
410    pub fn ec_dec_update(&mut self, fl: u32, fh: u32, ft: u32) {
411        if ft == 0 || fh > ft || fl >= fh {
412            self.error = true;
413            return;
414        }
415        self.dec_update(fl, fh, ft);
416    }
417
418    // ----- internal helpers -----
419
420    /// `ec_decode(ft)` per RFC 6716 §4.1.2: compute the symbol-proxy
421    /// `fs = ft - min(val / (rng / ft) + 1, ft)`.
422    fn decode(&mut self, ft: u32) -> u32 {
423        // The spec uses integer division. `rng/ft` is computed first;
424        // the divisor is then `val / (rng/ft)`. The renormalization
425        // invariant ensures `rng/ft >= 1` in all practical cases
426        // (rng > 2**23 and ft <= 2**16 on the symbol-decode path).
427        let s = self.rng / ft;
428        let approx = self.val / s + 1;
429        ft - approx.min(ft)
430    }
431
432    /// `ec_dec_update(fl, fh, ft)` per RFC 6716 §4.1.2.
433    ///
434    /// Narrows the range to the chosen symbol's interval, then runs
435    /// renormalization to restore `rng > 2**23`.
436    fn dec_update(&mut self, fl: u32, fh: u32, ft: u32) {
437        let s = self.rng / ft;
438        self.val -= s * (ft - fh);
439        if fl > 0 {
440            self.rng = s * (fh - fl);
441        } else {
442            self.rng -= s * (ft - fh);
443        }
444        self.normalize();
445    }
446
447    /// `ec_dec_normalize` per RFC 6716 §4.1.2.1.
448    ///
449    /// Until `rng > 2**23`, shift `rng` left by 8 and pull a fresh
450    /// `sym` byte. `sym` combines the previously-buffered low bit
451    /// (`rem`, as MSB) with the top 7 bits of the new byte; the LSB of
452    /// the new byte is buffered for next time. When the frame is
453    /// exhausted, zero bytes are substituted.
454    fn normalize(&mut self) {
455        while self.rng <= Self::RNG_MIN {
456            let byte = if self.fwd < self.buf.len() {
457                let b = self.buf[self.fwd];
458                self.fwd += 1;
459                b as u32
460            } else {
461                0
462            };
463            let sym = (self.rem << 7) | (byte >> 1);
464            self.rem = byte & 1;
465            self.rng <<= 8;
466            self.val = ((self.val << 8) + (255 - sym)) & 0x7FFF_FFFF;
467            // §4.1.6: each iteration adds 8 to nbits_total.
468            self.nbits_total = self.nbits_total.saturating_add(8);
469        }
470    }
471}
472
473#[cfg(test)]
474mod tests {
475    use super::*;
476
477    /// §4.1.1 initialization over an empty buffer must still satisfy
478    /// the §4.1.2.1 invariant and report `ec_tell() == 1`
479    /// (§4.1.6.1: "In a newly initialized decoder, before any symbols
480    /// have been read, this reports that 1 bit has been used").
481    #[test]
482    fn init_empty_buffer_satisfies_invariant() {
483        let dec = RangeDecoder::new(&[]);
484        assert!(dec.rng > RangeDecoder::RNG_MIN);
485        assert!(!dec.has_error());
486        assert_eq!(dec.tell(), 1);
487    }
488
489    /// Non-empty initialization also satisfies the invariant and
490    /// reports a sensible tell.
491    #[test]
492    fn init_nonempty_buffer_holds_invariant() {
493        let dec = RangeDecoder::new(&[0xAB, 0xCD, 0xEF, 0x12]);
494        assert!(dec.rng > RangeDecoder::RNG_MIN);
495        assert!(!dec.has_error());
496        assert!(dec.tell() >= 1);
497    }
498
499    /// `dec_bit_logp` should be statistically biased by the surrounding
500    /// bytes: an all-zero stream pushes `val` high, biasing toward "0",
501    /// and an all-ones stream pushes it low, biasing toward "1".
502    #[test]
503    fn dec_bit_logp_bias_with_extreme_inputs() {
504        // All-zero stream: bias toward "0".
505        let mut dec0 = RangeDecoder::new(&[0u8; 16]);
506        let mut zero_count = 0;
507        for _ in 0..32 {
508            if dec0.dec_bit_logp(1) == 0 {
509                zero_count += 1;
510            }
511        }
512        assert!(!dec0.has_error());
513        assert!(
514            zero_count > 16,
515            "all-zero stream should be biased toward 0: zero_count={}",
516            zero_count
517        );
518
519        // All-ones stream: bias toward "1".
520        let mut dec1 = RangeDecoder::new(&[0xFFu8; 16]);
521        let mut one_count = 0;
522        for _ in 0..32 {
523            if dec1.dec_bit_logp(1) == 1 {
524                one_count += 1;
525            }
526        }
527        assert!(!dec1.has_error());
528        assert!(
529            one_count > 16,
530            "all-ones stream should be biased toward 1: one_count={}",
531            one_count
532        );
533    }
534
535    /// `dec_bits` reads raw bits LSB-first from the END of the buffer.
536    /// With the last byte = 0b1010_0110, the first 4 raw bits returned
537    /// are 0b0110 = 6, and the next 4 are 0b1010 = 0xA.
538    #[test]
539    fn dec_bits_lsb_first_from_end() {
540        let mut dec = RangeDecoder::new(&[0x00, 0x00, 0xA6]);
541        let lo = dec.dec_bits(4);
542        let hi = dec.dec_bits(4);
543        assert_eq!(lo, 0x6);
544        assert_eq!(hi, 0xA);
545        assert!(!dec.has_error());
546    }
547
548    /// `dec_bits` past the end of the frame must zero-extend, per
549    /// §4.1.4 ("the decoder MUST continue to use zero for any further
550    /// input bytes required"). The function must not panic or set the
551    /// error flag in that case.
552    #[test]
553    fn dec_bits_zero_past_end_of_frame() {
554        let mut dec = RangeDecoder::new(&[0xFF, 0xFF]);
555        for _ in 0..4 {
556            let v = dec.dec_bits(4);
557            assert_eq!(v, 0xF);
558        }
559        // The next 8 bits should come back as zero (the range coder
560        // may or may not have shared bytes with the raw reader — but
561        // the *raw* side reads past-EOF as 0).
562        let pad = dec.dec_bits(8);
563        let _ = pad;
564        assert!(!dec.has_error());
565    }
566
567    /// `dec_uint(1)` is degenerate — the only value in `0..1` is 0 —
568    /// and consumes no bits.
569    #[test]
570    fn dec_uint_ft_one_is_zero_no_consumption() {
571        let mut dec = RangeDecoder::new(&[0x12, 0x34, 0x56]);
572        let before = dec.tell();
573        let v = dec.dec_uint(1).expect("ft=1 must succeed");
574        let after = dec.tell();
575        assert_eq!(v, 0);
576        assert_eq!(after, before);
577    }
578
579    /// `dec_uint` with `ft` in the small (`ftb <= 8`) regime: returned
580    /// values must lie in `[0, ft)` and never trip the error flag for
581    /// well-formed inputs.
582    #[test]
583    fn dec_uint_small_ft_in_range() {
584        let mut dec = RangeDecoder::new(&[0x42, 0x18, 0xC3, 0x7F]);
585        for _ in 0..8 {
586            let v = dec.dec_uint(200).expect("ft=200 must succeed");
587            assert!(v < 200, "v={} out of range", v);
588        }
589        assert!(!dec.has_error());
590    }
591
592    /// `dec_uint` with `ft` in the large (`ftb > 8`) regime: returned
593    /// values must lie in `[0, ft)`. The saturation path is allowed
594    /// to set the error flag, but the returned value remains bounded.
595    #[test]
596    fn dec_uint_large_ft_in_range() {
597        let buf: Vec<u8> = (0..64).collect();
598        let mut dec = RangeDecoder::new(&buf);
599        for _ in 0..8 {
600            let v = dec.dec_uint(1_000_000).expect("ft=1_000_000 must succeed");
601            assert!(v < 1_000_000, "v={} out of range", v);
602        }
603    }
604
605    /// `dec_uint` with `ft = 0` is degenerate and returns 0 without
606    /// consumption.
607    #[test]
608    fn dec_uint_ft_zero_returns_zero() {
609        let mut dec = RangeDecoder::new(&[0xAA, 0xBB, 0xCC, 0xDD]);
610        let before = dec.tell();
611        let v = dec.dec_uint(0).expect("ft=0 must succeed");
612        assert_eq!(v, 0);
613        assert_eq!(dec.tell(), before);
614    }
615
616    /// `tell()` must monotonically non-decrease across operations.
617    #[test]
618    fn tell_is_monotonic_across_decodes() {
619        let mut dec = RangeDecoder::new(&[0x55; 8]);
620        let mut prev = dec.tell();
621        for _ in 0..16 {
622            let _ = dec.dec_bit_logp(2);
623            let now = dec.tell();
624            assert!(now >= prev, "tell() went backwards: {} -> {}", prev, now);
625            prev = now;
626        }
627    }
628
629    /// `decode_bin(ftb)` must agree with the generic `decode(1<<ftb)`
630    /// path bit-for-bit (RFC 6716 §4.1.3.1: the two are mathematically
631    /// equivalent). Drive both with the same input bytes and compare.
632    #[test]
633    fn decode_bin_matches_generic_decode() {
634        for &ftb in &[1u32, 4, 8, 12, 15] {
635            let buf = [0x37u8, 0x91, 0xC4, 0x18, 0xA2, 0x5D, 0x6E, 0xFF];
636            let mut a = RangeDecoder::new(&buf);
637            let mut b = RangeDecoder::new(&buf);
638            let from_bin = a.decode_bin(ftb);
639            let from_generic = b.decode(1u32 << ftb);
640            assert_eq!(
641                from_bin, from_generic,
642                "decode_bin({ftb}) != decode(1<<{ftb})"
643            );
644            assert!(from_bin < (1u32 << ftb), "fs={from_bin} out of range");
645        }
646    }
647
648    /// RFC 6716 §4.1.6.1 specifies the identity
649    /// `ec_tell() == ceil(ec_tell_frac() / 8.0)`. Walk a decoder
650    /// forward through mixed symbol and raw-bit reads and assert this
651    /// at every step.
652    #[test]
653    fn tell_frac_consistent_with_tell() {
654        let mut dec = RangeDecoder::new(&[0xA3, 0x7F, 0x10, 0x5C, 0xE8, 0x91, 0x42, 0xB7]);
655        // §4.1.6.1: a fresh decoder reports tell() == 1.
656        assert_eq!(dec.tell(), 1);
657        for _ in 0..12 {
658            let whole = dec.tell();
659            let frac = dec.tell_frac();
660            let ceil_eighths = frac.div_ceil(8);
661            assert_eq!(
662                ceil_eighths, whole,
663                "tell()={whole} != ceil(tell_frac()={frac} / 8)={ceil_eighths}"
664            );
665            let _ = dec.dec_bit_logp(1);
666            let _ = dec.dec_bits(2);
667        }
668    }
669
670    /// `tell_frac()` of a fresh decoder sits in `[1, 8]` (since
671    /// `tell()` is `1` and the §4.1.6.1 ceiling identity holds).
672    #[test]
673    fn tell_frac_initial_within_one_bit() {
674        let dec = RangeDecoder::new(&[0xCC, 0xDD, 0xEE, 0xFF]);
675        let frac = dec.tell_frac();
676        assert!(
677            (1..=8).contains(&frac),
678            "tell_frac initial out of [1,8]: {frac}"
679        );
680        assert!(frac.div_ceil(8) == dec.tell());
681    }
682
683    /// `dec_icdf` over a binary `{ft - 1, 1}/ft` distribution must
684    /// agree with `dec_bit_logp(logp)` step-for-step — both are
685    /// special cases of `ec_decode` with `ft = 1<<ftb` (RFC 6716
686    /// §4.1.3.2 + §4.1.3.3).
687    #[test]
688    fn dec_icdf_matches_dec_bit_logp_for_binary() {
689        let buf = [0xDE, 0xAD, 0xBE, 0xEF, 0x10, 0x32, 0x54, 0x76];
690        // logp = 3 → ft = 8, P("1") = 1/8. icdf {ft-fh[0], ft-fh[1]} =
691        // {1, 0}: symbol 0 is the high-probability outcome (the "0"
692        // bit).
693        let logp = 3u32;
694        let icdf = [1u8, 0];
695        let mut a = RangeDecoder::new(&buf);
696        let mut b = RangeDecoder::new(&buf);
697        for _ in 0..16 {
698            let via_logp = a.dec_bit_logp(logp);
699            let via_icdf = b.dec_icdf(&icdf, logp);
700            assert_eq!(
701                via_logp, via_icdf,
702                "dec_bit_logp({logp}) != dec_icdf({icdf:?}, {logp})"
703            );
704        }
705        assert!(!a.has_error() && !b.has_error());
706    }
707
708    /// `dec_icdf` over a uniform `{1,1,1,1,1,1,1,1}/8` PDF must return
709    /// a symbol in `[0, 8)` every time without error.
710    #[test]
711    fn dec_icdf_uniform_returns_in_range() {
712        // Uniform 8-way PDF: fh = {1,2,3,4,5,6,7,8} → icdf =
713        // {7,6,5,4,3,2,1,0}.
714        let icdf = [7u8, 6, 5, 4, 3, 2, 1, 0];
715        let mut dec = RangeDecoder::new(&[0x42, 0x18, 0xC3, 0x7F, 0x55, 0xAA, 0x33, 0xCC]);
716        for _ in 0..16 {
717            let k = dec.dec_icdf(&icdf, 3);
718            assert!(k < 8, "icdf uniform returned {k} out of [0, 8)");
719        }
720        assert!(!dec.has_error());
721    }
722
723    /// `dec_icdf` over the degenerate single-symbol table `{0}` (only
724    /// the terminator) means symbol 0 covers the whole interval, so it
725    /// is always returned. No range mass is consumed and the error
726    /// flag stays clear.
727    #[test]
728    fn dec_icdf_single_symbol_always_zero() {
729        let icdf = [0u8];
730        let mut dec = RangeDecoder::new(&[0x77, 0x33, 0x11, 0xAA]);
731        let before_tell = dec.tell();
732        for _ in 0..4 {
733            let k = dec.dec_icdf(&icdf, 3);
734            assert_eq!(k, 0);
735        }
736        assert!(dec.tell() >= before_tell);
737        assert!(!dec.has_error());
738    }
739
740    /// `tell_frac()` is monotonically non-decreasing across mixed ops
741    /// (§4.1.6.2 inherits the monotonicity of `ec_tell` since the
742    /// procedure only adds bits).
743    #[test]
744    fn tell_frac_is_monotonic() {
745        let mut dec = RangeDecoder::new(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]);
746        // Uniform 8-way icdf so each call burns ~3 bits.
747        let icdf = [7u8, 6, 5, 4, 3, 2, 1, 0];
748        let mut prev = dec.tell_frac();
749        for i in 0..24 {
750            match i % 3 {
751                0 => {
752                    let _ = dec.dec_bit_logp(2);
753                }
754                1 => {
755                    let _ = dec.dec_icdf(&icdf, 3);
756                }
757                _ => {
758                    let _ = dec.dec_bits(2);
759                }
760            }
761            let now = dec.tell_frac();
762            assert!(
763                now >= prev,
764                "tell_frac() went backwards: {} -> {}",
765                prev,
766                now
767            );
768            prev = now;
769        }
770    }
771
772    /// `dec_bits(0)` returns 0 and consumes nothing.
773    #[test]
774    fn dec_bits_zero_width_is_noop() {
775        let mut dec = RangeDecoder::new(&[0x12, 0x34, 0x56]);
776        let before = dec.tell();
777        let v = dec.dec_bits(0);
778        assert_eq!(v, 0);
779        assert_eq!(dec.tell(), before);
780        assert!(!dec.has_error());
781    }
782
783    /// `dec_bits` with an over-large width sets the error flag and
784    /// returns 0 (guard against caller misuse).
785    #[test]
786    fn dec_bits_oversize_latches_error() {
787        let mut dec = RangeDecoder::new(&[0xAA, 0xBB, 0xCC, 0xDD]);
788        let v = dec.dec_bits(33);
789        assert_eq!(v, 0);
790        assert!(dec.has_error());
791    }
792
793    /// The public two-step `ec_decode` / `ec_dec_update` path must
794    /// reproduce, symbol for symbol, what the fused `dec_icdf` produces
795    /// for the same fixed PDF. This is the RFC 6716 §4.1.2 ↔ §4.1.3.3
796    /// equivalence: `dec_icdf` is exactly `ec_decode(1<<ftb)` followed
797    /// by a search and `ec_dec_update`. We drive both decoders over
798    /// identical input bytes and assert they stay in lockstep.
799    #[test]
800    fn ec_decode_update_matches_dec_icdf_for_fixed_pdf() {
801        // Uniform 8-way PDF: fh = {1,2,..,8}, ft = 8, icdf = {7,..,0}.
802        let icdf = [7u8, 6, 5, 4, 3, 2, 1, 0];
803        let ftb = 3u32;
804        let ft = 1u32 << ftb;
805        let buf = [0x42u8, 0x18, 0xC3, 0x7F, 0x55, 0xAA, 0x33, 0xCC];
806        let mut fused = RangeDecoder::new(&buf);
807        let mut split = RangeDecoder::new(&buf);
808        for _ in 0..16 {
809            let k_fused = fused.dec_icdf(&icdf, ftb);
810
811            // Reconstruct the same decode via the public split steps.
812            let fs = split.ec_decode(ft);
813            // icdf[k] == ft - fh[k]; fl[k] == fh[k-1] (fl[0] == 0).
814            // Find the symbol whose [fl, fh) contains fs.
815            let mut k_split = 0u32;
816            let mut fl = 0u32;
817            let mut fh = ft - icdf[0] as u32;
818            for (idx, w) in icdf.windows(2).enumerate() {
819                if fs < fh {
820                    break;
821                }
822                fl = ft - w[0] as u32;
823                fh = ft - w[1] as u32;
824                k_split = (idx + 1) as u32;
825            }
826            split.ec_dec_update(fl, fh, ft);
827
828            assert_eq!(
829                k_fused, k_split,
830                "fused dec_icdf and split ec_decode/ec_dec_update diverged"
831            );
832        }
833        assert!(!fused.has_error() && !split.has_error());
834    }
835
836    /// `ec_decode(ft)` returns a value in `[0, ft)` for every well-formed
837    /// `ft`, matching the §4.1.2 derivation `fs = ft - min(.., ft)`.
838    #[test]
839    fn ec_decode_returns_in_range() {
840        let buf = [0x37u8, 0x91, 0xC4, 0x18, 0xA2, 0x5D, 0x6E, 0xFF];
841        for &ft in &[2u32, 7, 100, 1000, 1 << 16] {
842            let mut dec = RangeDecoder::new(&buf);
843            let fs = dec.ec_decode(ft);
844            assert!(fs < ft, "ec_decode({ft}) = {fs} out of [0, {ft})");
845            assert!(!dec.has_error());
846        }
847    }
848
849    /// `ec_decode(0)` is malformed (division by zero in the §4.1.2
850    /// formula); it must latch the error flag and return 0 rather than
851    /// panic.
852    #[test]
853    fn ec_decode_ft_zero_latches_error() {
854        let mut dec = RangeDecoder::new(&[0x11, 0x22, 0x33, 0x44]);
855        let fs = dec.ec_decode(0);
856        assert_eq!(fs, 0);
857        assert!(dec.has_error());
858    }
859
860    /// `ec_dec_update` with a malformed tuple (`fl >= fh`, `fh > ft`,
861    /// or `ft == 0`) latches the error flag and leaves state untouched,
862    /// guarding against an underflow of `val` or a zeroing of `rng`.
863    #[test]
864    fn ec_dec_update_rejects_malformed_tuple() {
865        // fl >= fh
866        let mut a = RangeDecoder::new(&[0xAA, 0xBB, 0xCC, 0xDD]);
867        a.ec_dec_update(4, 4, 8);
868        assert!(a.has_error());
869
870        // fh > ft
871        let mut b = RangeDecoder::new(&[0xAA, 0xBB, 0xCC, 0xDD]);
872        b.ec_dec_update(0, 9, 8);
873        assert!(b.has_error());
874
875        // ft == 0
876        let mut c = RangeDecoder::new(&[0xAA, 0xBB, 0xCC, 0xDD]);
877        c.ec_dec_update(0, 1, 0);
878        assert!(c.has_error());
879    }
880
881    /// The public split path must also reproduce the `dec_uint` small
882    /// regime (`ftb <= 8`), which is internally `decode(ft)` followed by
883    /// `dec_update(t, t+1, ft)`. Drive `dec_uint` and the public
884    /// `ec_decode` / `ec_dec_update` in lockstep for a small `ft`.
885    #[test]
886    fn ec_decode_update_matches_dec_uint_small_regime() {
887        let buf = [0x42u8, 0x18, 0xC3, 0x7F, 0x55, 0xAA, 0x33, 0xCC];
888        let ft = 200u32; // ftb <= 8 → small dec_uint regime
889        let mut via_uint = RangeDecoder::new(&buf);
890        let mut via_split = RangeDecoder::new(&buf);
891        for _ in 0..8 {
892            let u = via_uint.dec_uint(ft).expect("ft=200 small regime");
893            let t = via_split.ec_decode(ft);
894            via_split.ec_dec_update(t, t + 1, ft);
895            assert_eq!(u, t, "dec_uint and split ec_decode/update diverged");
896        }
897        assert!(!via_uint.has_error() && !via_split.has_error());
898    }
899}