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}