1pub trait BitRead {
22 fn fill(&mut self);
24 fn peek_no_fill(&self, n: u32) -> u32;
26 fn skip_no_fill(&mut self, n: u32);
28 fn byte_position(&self) -> usize;
30 fn overrun(&self) -> usize;
33 fn buffered(&self) -> u32;
35
36 #[inline]
39 fn past_end(&self) -> usize {
40 self.overrun().saturating_sub(self.buffered() as usize / 8)
41 }
42
43 #[inline(always)]
45 fn fill_to(&mut self, n: u32) {
46 if self.buffered() < n {
47 self.refill_force();
48 }
49 }
50 fn refill_force(&mut self);
52
53 #[inline(always)]
54 fn peek(&mut self, n: u32) -> u32 {
55 self.fill();
56 self.peek_no_fill(n)
57 }
58 #[inline(always)]
59 fn get(&mut self, n: u32) -> u32 {
60 self.fill();
61 let v = self.peek_no_fill(n);
62 self.skip_no_fill(n);
63 v
64 }
65 #[inline(always)]
66 fn skip(&mut self, mut n: u32) {
67 while n > 32 {
68 self.fill();
69 self.skip_no_fill(32);
70 n -= 32;
71 }
72 self.fill();
73 self.skip_no_fill(n);
74 }
75 #[inline(always)]
77 fn bit(&mut self) -> u32 {
78 self.get(1)
79 }
80 #[inline]
82 fn exhausted(&self) -> bool {
83 self.overrun() > 8
86 }
87}
88
89#[inline(always)]
90fn mask(n: u32) -> u64 {
91 (1u64 << n) - 1
92}
93
94macro_rules! common_fields {
95 () => {
96 pub fn new(data: &'a [u8]) -> Self {
98 Self { data, pos: 0, cache: 0, bits: 0, overrun: 0 }
99 }
100 pub fn data(&self) -> &'a [u8] {
102 self.data
103 }
104 #[inline(always)]
106 pub fn buffered_bits(&self) -> u32 {
107 self.bits
108 }
109 };
110}
111
112#[derive(Clone, Copy)]
114pub struct BitPumpMsb<'a> {
115 data: &'a [u8],
116 pos: usize,
117 cache: u64,
119 bits: u32,
120 overrun: usize,
121}
122
123impl<'a> BitPumpMsb<'a> {
124 common_fields!();
125
126 #[cold]
129 #[inline(never)]
130 fn filled_slow(mut self) -> Self {
131 self.fill_slow();
132 self
133 }
134
135 fn fill_slow(&mut self) {
136 while self.bits <= 56 {
137 let b = match self.data.get(self.pos) {
138 Some(&b) => b,
139 None => {
140 self.overrun += 1;
141 0
142 }
143 };
144 self.pos += 1;
145 self.cache |= (b as u64) << (56 - self.bits);
146 self.bits += 8;
147 }
148 }
149
150 pub fn align_byte(&mut self) {
152 let r = self.bits % 8;
153 self.skip_no_fill(r);
154 }
155
156 #[inline(always)]
158 pub fn bit_position(&self) -> u64 {
159 self.pos as u64 * 8 - self.bits as u64
160 }
161
162 pub fn at_bit(data: &'a [u8], bit: u64) -> Self {
164 let mut p = Self::new(data.get((bit / 8) as usize..).unwrap_or(&[]));
165 p.fill();
166 p.skip_no_fill((bit % 8) as u32);
167 p.pos += (bit / 8) as usize;
168 p.data = data;
169 p
170 }
171}
172
173impl BitRead for BitPumpMsb<'_> {
174 #[inline(always)]
175 fn fill(&mut self) {
176 if self.bits >= 32 {
177 return;
178 }
179 self.refill_force();
180 }
181 #[inline(always)]
182 fn refill_force(&mut self) {
183 if let Some(chunk) = self.data.get(self.pos..self.pos + 8) {
184 let w = u64::from_be_bytes(chunk.try_into().unwrap());
185 self.cache |= w >> self.bits;
186 self.pos += ((63 - self.bits) >> 3) as usize;
187 self.bits |= 56;
188 } else {
189 *self = self.filled_slow();
190 }
191 }
192 #[inline(always)]
193 fn peek_no_fill(&self, n: u32) -> u32 {
194 (self.cache.rotate_left(n) & mask(n)) as u32
195 }
196 #[inline(always)]
197 fn skip_no_fill(&mut self, n: u32) {
198 debug_assert!(n <= self.bits);
199 self.cache <<= n;
200 self.bits -= n;
201 }
202 fn byte_position(&self) -> usize {
203 self.pos - (self.bits as usize >> 3)
204 }
205 fn overrun(&self) -> usize {
206 self.overrun
207 }
208 fn buffered(&self) -> u32 {
209 self.bits
210 }
211}
212
213#[derive(Clone)]
215pub struct BitPumpLsb<'a> {
216 data: &'a [u8],
217 pos: usize,
218 cache: u64,
220 bits: u32,
221 overrun: usize,
222}
223
224impl<'a> BitPumpLsb<'a> {
225 common_fields!();
226
227 #[cold]
228 fn fill_slow(&mut self) {
229 while self.bits <= 56 {
230 let b = match self.data.get(self.pos) {
231 Some(&b) => b,
232 None => {
233 self.overrun += 1;
234 0
235 }
236 };
237 self.pos += 1;
238 self.cache |= (b as u64) << self.bits;
239 self.bits += 8;
240 }
241 }
242}
243
244impl BitRead for BitPumpLsb<'_> {
245 #[inline(always)]
246 fn fill(&mut self) {
247 if self.bits >= 32 {
248 return;
249 }
250 self.refill_force();
251 }
252 #[inline(always)]
253 fn refill_force(&mut self) {
254 if let Some(chunk) = self.data.get(self.pos..self.pos + 8) {
255 let w = u64::from_le_bytes(chunk.try_into().unwrap());
256 self.cache |= w << self.bits;
257 self.pos += ((63 - self.bits) >> 3) as usize;
258 self.bits |= 56;
259 } else {
260 self.fill_slow();
261 }
262 }
263 #[inline(always)]
264 fn peek_no_fill(&self, n: u32) -> u32 {
265 (self.cache & mask(n)) as u32
266 }
267 #[inline(always)]
268 fn skip_no_fill(&mut self, n: u32) {
269 debug_assert!(n <= self.bits);
270 self.cache >>= n;
271 self.bits -= n;
272 }
273 fn byte_position(&self) -> usize {
274 self.pos - (self.bits as usize >> 3)
275 }
276 fn overrun(&self) -> usize {
277 self.overrun
278 }
279 fn buffered(&self) -> u32 {
280 self.bits
281 }
282}
283
284#[derive(Clone)]
286pub struct BitPumpMsbWords<'a, const W: usize> {
287 data: &'a [u8],
288 pos: usize,
289 cache: u64,
290 bits: u32,
291 overrun: usize,
292}
293
294pub type BitPumpMsb16<'a> = BitPumpMsbWords<'a, 2>;
296pub type BitPumpMsb32<'a> = BitPumpMsbWords<'a, 4>;
298
299impl<'a, const W: usize> BitPumpMsbWords<'a, W> {
300 common_fields!();
301
302 #[inline(always)]
304 pub fn bit_position(&self) -> u64 {
305 self.pos as u64 * 8 - self.bits as u64
306 }
307
308 pub fn at_bit(data: &'a [u8], bit: u64) -> Self {
310 let word_bits = 8 * W as u64;
311 let base = (bit / word_bits) as usize * W;
312 let mut p = Self::new(data.get(base..).unwrap_or(&[]));
313 p.fill();
314 p.skip_no_fill((bit % word_bits) as u32);
315 p.pos += base;
316 p.data = data;
317 p
318 }
319
320 #[cold]
321 fn fill_slow(&mut self) {
322 while self.bits <= 64 - 8 * W as u32 {
323 let mut w: u64 = 0;
324 for i in (0..W).rev() {
325 let b = match self.data.get(self.pos + i) {
326 Some(&b) => b,
327 None => {
328 self.overrun += 1;
329 0
330 }
331 };
332 w = (w << 8) | b as u64;
333 }
334 self.pos += W;
335 self.cache |= w << (64 - 8 * W as u32 - self.bits);
336 self.bits += 8 * W as u32;
337 }
338 }
339}
340
341impl<const W: usize> BitRead for BitPumpMsbWords<'_, W> {
342 #[inline(always)]
343 fn fill(&mut self) {
344 if self.bits >= 32 {
345 return;
346 }
347 self.refill_force();
348 }
349 #[inline(always)]
350 fn refill_force(&mut self) {
351 if let Some(chunk) = self.data.get(self.pos..self.pos + 8) {
352 let le = u64::from_le_bytes(chunk.try_into().unwrap());
353 let w = if W == 2 {
355 let x = le;
356 ((x & 0xFFFF) << 48) | ((x & 0xFFFF_0000) << 16) | ((x >> 16) & 0xFFFF_0000) | (x >> 48)
357 } else {
358 le.rotate_left(32)
359 };
360 let words = (64 - self.bits) / (8 * W as u32);
362 let take = words * 8 * W as u32;
363 let part = if take == 64 { w } else { w >> (64 - take) << (64 - take) };
364 self.cache |= part >> self.bits;
365 self.bits += take;
366 self.pos += (take / 8) as usize;
367 } else {
368 self.fill_slow();
369 }
370 }
371 #[inline(always)]
372 fn peek_no_fill(&self, n: u32) -> u32 {
373 (self.cache.rotate_left(n) & mask(n)) as u32
374 }
375 #[inline(always)]
376 fn skip_no_fill(&mut self, n: u32) {
377 debug_assert!(n <= self.bits);
378 self.cache = if n == 64 { 0 } else { self.cache << n };
379 self.bits -= n;
380 }
381 fn byte_position(&self) -> usize {
382 self.pos - (self.bits as usize >> 3)
383 }
384 fn overrun(&self) -> usize {
385 self.overrun
386 }
387 fn buffered(&self) -> u32 {
388 self.bits
389 }
390}
391
392#[derive(Clone)]
395pub struct BitPumpJpeg<'a> {
396 data: &'a [u8],
397 pos: usize,
398 cache: u64,
399 bits: u32,
400 overrun: usize,
401 marker_hit: bool,
402}
403
404impl<'a> BitPumpJpeg<'a> {
405 pub fn new(data: &'a [u8]) -> Self {
406 Self { data, pos: 0, cache: 0, bits: 0, overrun: 0, marker_hit: false }
407 }
408 pub fn marker_hit(&self) -> bool {
410 self.marker_hit
411 }
412 pub fn raw_position(&self) -> usize {
414 self.pos
415 }
416
417 #[cold]
418 fn fill_slow(&mut self) {
419 while self.bits <= 56 {
420 let mut b = 0u8;
421 if !self.marker_hit {
422 match self.data.get(self.pos) {
423 Some(&0xFF) => {
424 match self.data.get(self.pos + 1) {
425 Some(&0x00) => {
426 b = 0xFF;
427 self.pos += 2;
428 }
429 _ => {
430 self.marker_hit = true;
432 self.overrun += 1;
433 }
434 }
435 }
436 Some(&v) => {
437 b = v;
438 self.pos += 1;
439 }
440 None => {
441 self.marker_hit = true;
442 self.overrun += 1;
443 }
444 }
445 } else {
446 self.overrun += 1;
447 }
448 self.cache |= (b as u64) << (56 - self.bits);
449 self.bits += 8;
450 }
451 }
452
453 pub fn reset_at_restart(&mut self) -> bool {
455 let mut p = self.byte_position_raw_estimate();
457 while p + 1 < self.data.len() {
458 if self.data[p] == 0xFF && (0xD0..=0xD7).contains(&self.data[p + 1]) {
459 self.pos = p + 2;
460 self.cache = 0;
461 self.bits = 0;
462 self.marker_hit = false;
463 self.overrun = 0;
466 return true;
467 }
468 p += 1;
469 }
470 false
471 }
472
473 fn byte_position_raw_estimate(&self) -> usize {
474 self.pos.saturating_sub(((self.bits as usize) >> 3) * 2)
476 }
477}
478
479impl BitRead for BitPumpJpeg<'_> {
480 #[inline(always)]
481 fn fill(&mut self) {
482 if self.bits >= 32 {
483 return;
484 }
485 self.refill_force();
486 }
487 #[inline(always)]
488 fn refill_force(&mut self) {
489 if let Some(chunk) = self.data.get(self.pos..self.pos + 8) {
490 let w = u64::from_be_bytes(chunk.try_into().unwrap());
491 let inv = !w;
493 let has_ff = (inv.wrapping_sub(0x0101_0101_0101_0101) & !inv & 0x8080_8080_8080_8080) != 0;
494 if !has_ff {
495 self.cache |= w >> self.bits;
496 self.pos += ((63 - self.bits) >> 3) as usize;
497 self.bits |= 56;
498 return;
499 }
500 }
501 self.fill_slow();
502 }
503 #[inline(always)]
504 fn peek_no_fill(&self, n: u32) -> u32 {
505 (self.cache.rotate_left(n) & mask(n)) as u32
506 }
507 #[inline(always)]
508 fn skip_no_fill(&mut self, n: u32) {
509 debug_assert!(n <= self.bits);
510 self.cache <<= n;
511 self.bits -= n;
512 }
513 fn byte_position(&self) -> usize {
514 self.pos.saturating_sub(self.bits as usize >> 3)
515 }
516 fn overrun(&self) -> usize {
517 self.overrun
518 }
519 fn buffered(&self) -> u32 {
520 self.bits
521 }
522}
523
524#[inline(always)]
526pub fn extend_diff(v: u32, len: u32) -> i32 {
527 if len == 0 {
528 return 0;
529 }
530 let v = v as i32;
531 if v & (1 << (len - 1)) == 0 { v - (1 << len) + 1 } else { v }
532}
533
534#[cfg(test)]
535mod tests {
536 use super::*;
537
538 fn ref_msb(data: &[u8], widths: &[u32]) -> Vec<u32> {
539 let mut out = vec![];
540 let mut bitpos = 0usize;
541 for &w in widths {
542 let mut v = 0u32;
543 for _ in 0..w {
544 let byte = data.get(bitpos / 8).copied().unwrap_or(0);
545 let bit = (byte >> (7 - bitpos % 8)) & 1;
546 v = (v << 1) | bit as u32;
547 bitpos += 1;
548 }
549 out.push(v);
550 }
551 out
552 }
553 fn ref_lsb(data: &[u8], widths: &[u32]) -> Vec<u32> {
554 let mut out = vec![];
555 let mut bitpos = 0usize;
556 for &w in widths {
557 let mut v = 0u32;
558 for i in 0..w {
559 let byte = data.get(bitpos / 8).copied().unwrap_or(0);
560 let bit = (byte >> (bitpos % 8)) & 1;
561 v |= (bit as u32) << i;
562 bitpos += 1;
563 }
564 out.push(v);
565 }
566 out
567 }
568 fn swap_words(data: &[u8], w: usize) -> Vec<u8> {
569 let mut d = data.to_vec();
570 d.resize(data.len().div_ceil(w) * w, 0);
571 for c in d.chunks_mut(w) {
572 c.reverse();
573 }
574 d
575 }
576
577 fn pseudo(n: usize, seed: u64) -> Vec<u8> {
578 let mut x = seed;
579 (0..n)
580 .map(|_| {
581 x ^= x << 13;
582 x ^= x >> 7;
583 x ^= x << 17;
584 x as u8
585 })
586 .collect()
587 }
588
589 #[test]
590 fn pumps_match_reference() {
591 for seed in 1..20u64 {
592 let data = pseudo(97, seed);
593 let widths: Vec<u32> = (0..120).map(|i| ((i * 7 + seed as usize) % 33) as u32).collect();
594 let mut m = BitPumpMsb::new(&data);
595 let got: Vec<u32> = widths.iter().map(|&w| m.get(w)).collect();
596 assert_eq!(got, ref_msb(&data, &widths), "msb seed {seed}");
597 let mut l = BitPumpLsb::new(&data);
598 let got: Vec<u32> = widths.iter().map(|&w| l.get(w)).collect();
599 assert_eq!(got, ref_lsb(&data, &widths), "lsb seed {seed}");
600 let mut m16 = BitPumpMsb16::new(&data);
601 let got: Vec<u32> = widths.iter().map(|&w| m16.get(w)).collect();
602 assert_eq!(got, ref_msb(&swap_words(&data, 2), &widths), "msb16 seed {seed}");
603 let mut m32 = BitPumpMsb32::new(&data);
604 let got: Vec<u32> = widths.iter().map(|&w| m32.get(w)).collect();
605 assert_eq!(got, ref_msb(&swap_words(&data, 4), &widths), "msb32 seed {seed}");
606 }
607 }
608
609 #[test]
610 fn jpeg_unstuffing() {
611 let data = [0x12, 0xFF, 0x00, 0x34, 0xFF, 0xD9, 0x55];
612 let mut p = BitPumpJpeg::new(&data);
613 assert_eq!(p.get(8), 0x12);
614 assert_eq!(p.get(8), 0xFF);
615 assert_eq!(p.get(8), 0x34);
616 assert_eq!(p.get(8), 0x00); assert!(p.marker_hit());
618 let mut d = pseudo(200, 3);
620 for b in d.iter_mut() {
621 if *b == 0xFF {
622 *b = 0xFE;
623 }
624 }
625 let mut stuffed = vec![];
626 for (i, &b) in d.iter().enumerate() {
627 stuffed.push(if i % 17 == 0 { 0xFF } else { b });
628 if i % 17 == 0 {
629 stuffed.push(0);
630 }
631 }
632 let plain: Vec<u8> = d.iter().enumerate().map(|(i, &b)| if i % 17 == 0 { 0xFF } else { b }).collect();
633 let widths: Vec<u32> = (0..300).map(|i| (i % 13) as u32 + 1).collect();
634 let mut p = BitPumpJpeg::new(&stuffed);
635 let got: Vec<u32> = widths.iter().map(|&w| p.get(w)).collect();
636 assert_eq!(got, ref_msb(&plain, &widths));
637 }
638
639 #[test]
640 fn overrun_is_tracked_not_panicking() {
641 let data = [0xAAu8; 3];
642 let mut p = BitPumpMsb::new(&data);
643 for _ in 0..100 {
644 p.get(32);
645 }
646 assert!(p.exhausted());
647 let mut p = BitPumpLsb::new(&[]);
648 assert_eq!(p.get(32), 0);
649 assert!(p.overrun() > 0);
650 }
651
652 #[test]
653 fn diff_extension() {
654 assert_eq!(extend_diff(0, 1), -1);
655 assert_eq!(extend_diff(1, 1), 1);
656 assert_eq!(extend_diff(0b010, 3), -5);
657 assert_eq!(extend_diff(0b110, 3), 6);
658 assert_eq!(extend_diff(0, 0), 0);
659 }
660}