1pub const HEADER_BYTES: usize = 8;
33pub const END_OF_BLOCK: u16 = 0xFE00;
35const V2_END_OF_FRAME: u32 = 0x1FF;
37
38#[derive(Clone, Copy, Debug, PartialEq, Eq)]
40pub enum DecodeError {
41 Truncated,
43 Version(u16),
45 BadCode,
47 OutputFull,
49 Overrun,
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55pub struct Header {
56 pub mdec_words: u16,
58 pub qscale: u16,
60 pub version: u16,
62}
63
64impl Header {
65 pub fn parse(frame: &[u8]) -> Result<Self, DecodeError> {
67 if frame.len() < HEADER_BYTES {
68 return Err(DecodeError::Truncated);
69 }
70 let h = |i: usize| u16::from_le_bytes([frame[i], frame[i + 1]]);
71 Ok(Header {
72 mdec_words: h(0),
73 qscale: h(4),
74 version: h(6),
75 })
76 }
77}
78
79const KIND_INVALID: u32 = 0;
82const KIND_CODE: u32 = 1;
83const KIND_ESCAPE: u32 = 2;
84const KIND_EOB: u32 = 3;
85const KIND_LONG: u32 = 4;
86
87const fn entry(kind: u32, len: u32, hw: u32) -> u32 {
88 (kind << 24) | (len << 16) | hw
89}
90
91const AC_CODES: [(u8, u16, u8, u8); 111] = [
94 (2, 0x3, 0, 1),
95 (3, 0x3, 1, 1),
96 (4, 0x4, 0, 2),
97 (4, 0x5, 2, 1),
98 (5, 0x05, 0, 3),
99 (5, 0x06, 4, 1),
100 (5, 0x07, 3, 1),
101 (6, 0x04, 7, 1),
102 (6, 0x05, 6, 1),
103 (6, 0x06, 1, 2),
104 (6, 0x07, 5, 1),
105 (7, 0x04, 2, 2),
106 (7, 0x05, 9, 1),
107 (7, 0x06, 0, 4),
108 (7, 0x07, 8, 1),
109 (8, 0x20, 13, 1),
110 (8, 0x21, 0, 6),
111 (8, 0x22, 12, 1),
112 (8, 0x23, 11, 1),
113 (8, 0x24, 3, 2),
114 (8, 0x25, 1, 3),
115 (8, 0x26, 0, 5),
116 (8, 0x27, 10, 1),
117 (10, 0x008, 16, 1),
118 (10, 0x009, 5, 2),
119 (10, 0x00A, 0, 7),
120 (10, 0x00B, 2, 3),
121 (10, 0x00C, 1, 4),
122 (10, 0x00D, 15, 1),
123 (10, 0x00E, 14, 1),
124 (10, 0x00F, 4, 2),
125 (12, 0x010, 0, 11),
126 (12, 0x011, 8, 2),
127 (12, 0x012, 4, 3),
128 (12, 0x013, 0, 10),
129 (12, 0x014, 2, 4),
130 (12, 0x015, 7, 2),
131 (12, 0x016, 21, 1),
132 (12, 0x017, 20, 1),
133 (12, 0x018, 0, 9),
134 (12, 0x019, 19, 1),
135 (12, 0x01A, 18, 1),
136 (12, 0x01B, 1, 5),
137 (12, 0x01C, 3, 3),
138 (12, 0x01D, 0, 8),
139 (12, 0x01E, 6, 2),
140 (12, 0x01F, 17, 1),
141 (13, 0x0010, 10, 2),
142 (13, 0x0011, 9, 2),
143 (13, 0x0012, 5, 3),
144 (13, 0x0013, 3, 4),
145 (13, 0x0014, 2, 5),
146 (13, 0x0015, 1, 7),
147 (13, 0x0016, 1, 6),
148 (13, 0x0017, 0, 15),
149 (13, 0x0018, 0, 14),
150 (13, 0x0019, 0, 13),
151 (13, 0x001A, 0, 12),
152 (13, 0x001B, 26, 1),
153 (13, 0x001C, 25, 1),
154 (13, 0x001D, 24, 1),
155 (13, 0x001E, 23, 1),
156 (13, 0x001F, 22, 1),
157 (14, 0x0010, 0, 31),
158 (14, 0x0011, 0, 30),
159 (14, 0x0012, 0, 29),
160 (14, 0x0013, 0, 28),
161 (14, 0x0014, 0, 27),
162 (14, 0x0015, 0, 26),
163 (14, 0x0016, 0, 25),
164 (14, 0x0017, 0, 24),
165 (14, 0x0018, 0, 23),
166 (14, 0x0019, 0, 22),
167 (14, 0x001A, 0, 21),
168 (14, 0x001B, 0, 20),
169 (14, 0x001C, 0, 19),
170 (14, 0x001D, 0, 18),
171 (14, 0x001E, 0, 17),
172 (14, 0x001F, 0, 16),
173 (15, 0x0010, 0, 40),
174 (15, 0x0011, 0, 39),
175 (15, 0x0012, 0, 38),
176 (15, 0x0013, 0, 37),
177 (15, 0x0014, 0, 36),
178 (15, 0x0015, 0, 35),
179 (15, 0x0016, 0, 34),
180 (15, 0x0017, 0, 33),
181 (15, 0x0018, 0, 32),
182 (15, 0x0019, 1, 14),
183 (15, 0x001A, 1, 13),
184 (15, 0x001B, 1, 12),
185 (15, 0x001C, 1, 11),
186 (15, 0x001D, 1, 10),
187 (15, 0x001E, 1, 9),
188 (15, 0x001F, 1, 8),
189 (16, 0x0010, 1, 18),
190 (16, 0x0011, 1, 17),
191 (16, 0x0012, 1, 16),
192 (16, 0x0013, 1, 15),
193 (16, 0x0014, 6, 3),
194 (16, 0x0015, 16, 2),
195 (16, 0x0016, 15, 2),
196 (16, 0x0017, 14, 2),
197 (16, 0x0018, 13, 2),
198 (16, 0x0019, 12, 2),
199 (16, 0x001A, 11, 2),
200 (16, 0x001B, 31, 1),
201 (16, 0x001C, 30, 1),
202 (16, 0x001D, 29, 1),
203 (16, 0x001E, 28, 1),
204 (16, 0x001F, 27, 1),
205];
206
207static SHORT: [u32; 256] = build_short();
211static LONG: [u32; 96] = build_long();
215
216const fn build_short() -> [u32; 256] {
217 let mut t = [entry(KIND_INVALID, 0, 0); 256];
218 let mut i = 0b1000_0000;
220 while i < 0b1100_0000 {
221 t[i] = entry(KIND_EOB, 2, 0);
222 i += 1;
223 }
224 let mut i = 0b0000_0100;
226 while i < 0b0000_1000 {
227 t[i] = entry(KIND_ESCAPE, 6, 0);
228 i += 1;
229 }
230 let mut i = 0;
232 while i < 0b0000_0100 {
233 t[i] = entry(KIND_LONG, 0, 0);
234 i += 1;
235 }
236 let mut c = 0;
237 while c < AC_CODES.len() {
238 let (len, code, run, level) = AC_CODES[c];
239 if len <= 8 {
240 let shift = 8 - len as usize;
241 let base = (code as usize) << shift;
242 let mut k = 0;
243 while k < (1 << shift) {
244 t[base + k] = entry(KIND_CODE, len as u32, ((run as u32) << 10) | level as u32);
245 k += 1;
246 }
247 }
248 c += 1;
249 }
250 t
251}
252
253const fn build_long() -> [u32; 96] {
254 let mut t = [entry(KIND_INVALID, 0, 0); 96];
255 let mut c = 0;
256 while c < AC_CODES.len() {
257 let (len, code, run, level) = AC_CODES[c];
258 if len >= 10 {
259 let significant = 16 - code.leading_zeros(); let lz = len as u32 - significant;
261 let suffix_bits = significant - 1;
262 let suffix = (code as u32) & ((1 << suffix_bits) - 1);
263 let base = ((lz - 6) * 16) as usize;
264 let hw = ((run as u32) << 10) | level as u32;
265 let pad = 4 - suffix_bits;
268 let first = (suffix << pad) as usize;
269 let mut k = 0;
270 while k < (1 << pad) {
271 t[base + first + k] = entry(KIND_CODE, len as u32, hw);
272 k += 1;
273 }
274 }
275 c += 1;
276 }
277 t
278}
279
280static FAST: [u32; 256] = build_fast();
285
286const fn build_fast() -> [u32; 256] {
287 let mut t = [0u32; 256];
288 let mut i = 0;
289 while i < 256 {
290 let e = SHORT[i];
291 t[i] = if e >> 24 == KIND_CODE {
292 ((((e >> 16) & 0x1F) + 1) << 16) | (e & 0xFFFF)
293 } else {
294 0x8000_0000
295 };
296 i += 1;
297 }
298 t
299}
300
301#[derive(Clone, Copy)]
308struct Bits<const ALIGNED: bool> {
309 p: *const u8,
312 end: *const u8,
313 buf: u32,
315 avail: u32,
317}
318
319impl<const ALIGNED: bool> Bits<ALIGNED> {
320 fn new(data: &[u8]) -> Self {
321 let p = data.as_ptr();
322 let mut b = Bits {
323 p,
324 end: p.wrapping_add(data.len() & !1),
325 buf: 0,
326 avail: 0,
327 };
328 b.refill();
329 b
330 }
331
332 #[inline(always)]
335 fn refill(&mut self) {
336 while self.avail <= 16 {
337 let hw = if self.p < self.end {
338 unsafe {
341 if ALIGNED {
342 u32::from(u16::from_le((self.p as *const u16).read()))
343 } else {
344 u32::from(*self.p) | u32::from(*self.p.add(1)) << 8
345 }
346 }
347 } else {
348 0
349 };
350 self.p = self.p.wrapping_add(2);
351 self.buf |= hw << (16 - self.avail);
352 self.avail += 16;
353 }
354 }
355
356 #[inline(always)]
357 fn skip(&mut self, n: u32) {
358 self.buf <<= n;
359 self.avail -= n;
360 self.refill();
361 }
362
363 #[inline(always)]
365 fn read(&mut self, n: u32) -> u32 {
366 let v = self.buf >> (32 - n);
367 self.skip(n);
368 v
369 }
370}
371
372pub fn decode_frame(
386 frame: &[u8],
387 out: &mut [u16],
388 max_macroblocks: u32,
389 pump_every: u32,
390 pump: &mut impl FnMut(),
391) -> Result<usize, DecodeError> {
392 let header = Header::parse(frame)?;
393 if !(1..=2).contains(&header.version) {
394 return Err(DecodeError::Version(header.version));
395 }
396 let body = &frame[HEADER_BYTES..];
397 let mut pump = || cold_pump(pump);
398 let n = if (body.as_ptr() as usize).is_multiple_of(2) {
399 decode_body::<true>(
400 body,
401 header.qscale,
402 out,
403 max_macroblocks,
404 pump_every,
405 &mut pump,
406 )?
407 } else {
408 decode_body::<false>(
409 body,
410 header.qscale,
411 out,
412 max_macroblocks,
413 pump_every,
414 &mut pump,
415 )?
416 };
417
418 let announced = header.mdec_words as usize * 2;
419 let mut padded = (n + 63) & !63;
420 if padded < announced {
421 padded = (announced + 63) & !63;
422 }
423 if padded > out.len() {
424 return Err(DecodeError::OutputFull);
425 }
426 for slot in &mut out[n..padded] {
427 *slot = END_OF_BLOCK;
428 }
429 Ok(padded / 2)
430}
431
432#[cold]
435#[inline(never)]
436fn cold_pump(pump: &mut impl FnMut()) {
437 pump();
438}
439
440#[inline(never)]
448fn decode_body<const ALIGNED: bool>(
449 body: &[u8],
450 qscale: u16,
451 out: &mut [u16],
452 max_macroblocks: u32,
453 pump_every: u32,
454 pump: &mut impl FnMut(),
455) -> Result<usize, DecodeError> {
456 let qscale = ((qscale as u32) & 0x3F) << 10;
457 let mut bits = Bits::<ALIGNED>::new(body);
458 let overrun = body.as_ptr().wrapping_add((body.len() + 4) & !1);
461 let o0 = out.as_mut_ptr();
462 let oend = o0.wrapping_add(out.len());
463 let mut o = o0;
464 let mut mb = 0u32;
465 let mut since_pump = 0u32;
466
467 'frame: while mb < max_macroblocks {
470 for block in 0..6 {
471 let dc = bits.read(10);
472 if dc == V2_END_OF_FRAME && block == 0 {
473 break 'frame;
474 }
475 if o == oend {
476 return Err(DecodeError::OutputFull);
477 }
478 unsafe { o.write((qscale | dc) as u16) };
480 o = o.wrapping_add(1);
481 loop {
482 let e = FAST[(bits.buf >> 24) as usize];
483 let hw = if (e as i32) >= 0 {
484 let used = e >> 16;
486 let sign = ((bits.buf << (used - 1)) as i32 >> 31) as u32;
487 bits.skip(used);
488 let level = ((e & 0x3FF) ^ sign).wrapping_sub(sign) & 0x3FF;
489 (e & 0xFC00) | level
490 } else {
491 match slow_code(&mut bits) {
492 Ok(Some(hw)) => hw,
493 Ok(None) => {
494 if o == oend {
495 return Err(DecodeError::OutputFull);
496 }
497 unsafe { o.write(END_OF_BLOCK) };
499 o = o.wrapping_add(1);
500 break;
501 }
502 Err(e) => return Err(e),
503 }
504 };
505 if o == oend {
506 return Err(DecodeError::OutputFull);
507 }
508 unsafe { o.write(hw as u16) };
510 o = o.wrapping_add(1);
511 }
512 if bits.p > overrun {
513 return Err(DecodeError::Overrun);
514 }
515 }
516 mb += 1;
517 since_pump += 1;
518 if since_pump == pump_every {
519 since_pump = 0;
520 pump();
521 }
522 }
523 Ok(unsafe { o.offset_from(o0) } as usize)
525}
526
527#[inline(always)]
531fn slow_code<const ALIGNED: bool>(bits: &mut Bits<ALIGNED>) -> Result<Option<u32>, DecodeError> {
532 match SHORT[(bits.buf >> 24) as usize] >> 24 {
533 KIND_EOB => {
534 bits.skip(2);
535 Ok(None)
536 }
537 KIND_ESCAPE => {
538 bits.skip(6);
539 Ok(Some(bits.read(16)))
540 }
541 KIND_LONG => {
542 let lz = bits.buf.leading_zeros();
543 if !(6..=11).contains(&lz) {
544 return Err(DecodeError::BadCode);
545 }
546 let next4 = (bits.buf << (lz + 1)) >> 28;
547 let e2 = LONG[((lz - 6) * 16 + next4) as usize];
548 if e2 >> 24 != KIND_CODE {
549 return Err(DecodeError::BadCode);
550 }
551 bits.skip((e2 >> 16) & 0x1F);
552 let negative = bits.read(1) != 0;
553 let hw = e2 & 0xFFFF;
554 Ok(Some(if negative {
555 (hw & 0xFC00) | ((0u32.wrapping_sub(hw & 0x3FF)) & 0x3FF)
556 } else {
557 hw
558 }))
559 }
560 _ => Err(DecodeError::BadCode),
561 }
562}
563
564#[cfg(test)]
565mod tests {
566 extern crate std;
567 use super::*;
568
569 mod reference {
572 use super::super::*;
573
574 struct Bits<'a> {
575 data: &'a [u8],
576 pos: usize,
577 buf: u32,
578 avail: u32,
579 }
580
581 impl<'a> Bits<'a> {
582 fn new(data: &'a [u8]) -> Self {
583 let mut b = Bits {
584 data,
585 pos: 0,
586 buf: 0,
587 avail: 0,
588 };
589 b.refill();
590 b
591 }
592 fn refill(&mut self) {
593 while self.avail <= 16 {
594 let hw = if self.pos + 1 < self.data.len() {
595 self.data[self.pos] as u32 | (self.data[self.pos + 1] as u32) << 8
596 } else {
597 0
598 };
599 self.pos += 2;
600 self.buf |= hw << (16 - self.avail);
601 self.avail += 16;
602 }
603 }
604 fn skip(&mut self, n: u32) {
605 self.buf <<= n;
606 self.avail -= n;
607 self.refill();
608 }
609 fn read(&mut self, n: u32) -> u32 {
610 let v = self.buf >> (32 - n);
611 self.skip(n);
612 v
613 }
614 fn overrun(&self) -> bool {
615 self.pos > self.data.len() + 4
616 }
617 }
618
619 pub fn decode_frame(
620 frame: &[u8],
621 out: &mut [u16],
622 max_macroblocks: u32,
623 ) -> Result<usize, DecodeError> {
624 let header = Header::parse(frame)?;
625 if !(1..=2).contains(&header.version) {
626 return Err(DecodeError::Version(header.version));
627 }
628 let qscale = ((header.qscale as u32) & 0x3F) << 10;
629 let mut bits = Bits::new(&frame[HEADER_BYTES..]);
630 let mut n = 0usize;
631 let mut mb = 0u32;
632 'frame: while mb < max_macroblocks {
633 for block in 0..6 {
634 let dc = bits.read(10);
635 if dc == V2_END_OF_FRAME && block == 0 {
636 break 'frame;
637 }
638 if n >= out.len() {
639 return Err(DecodeError::OutputFull);
640 }
641 out[n] = (qscale | dc) as u16;
642 n += 1;
643 loop {
644 let e = SHORT[(bits.buf >> 24) as usize];
645 let (len, hw) = match e >> 24 {
646 KIND_EOB => {
647 bits.skip(2);
648 if n >= out.len() {
649 return Err(DecodeError::OutputFull);
650 }
651 out[n] = END_OF_BLOCK;
652 n += 1;
653 break;
654 }
655 KIND_CODE => ((e >> 16) & 0x1F, e & 0xFFFF),
656 KIND_ESCAPE => {
657 bits.skip(6);
658 let raw = bits.read(16);
659 if n >= out.len() {
660 return Err(DecodeError::OutputFull);
661 }
662 out[n] = raw as u16;
663 n += 1;
664 continue;
665 }
666 KIND_LONG => {
667 let lz = bits.buf.leading_zeros();
668 if !(6..=11).contains(&lz) {
669 return Err(DecodeError::BadCode);
670 }
671 let next4 = (bits.buf << (lz + 1)) >> 28;
672 let e2 = LONG[((lz - 6) * 16 + next4) as usize];
673 if e2 >> 24 != KIND_CODE {
674 return Err(DecodeError::BadCode);
675 }
676 ((e2 >> 16) & 0x1F, e2 & 0xFFFF)
677 }
678 _ => return Err(DecodeError::BadCode),
679 };
680 bits.skip(len);
681 let negative = bits.read(1) != 0;
682 let hw = if negative {
683 (hw & 0xFC00) | ((0u32.wrapping_sub(hw & 0x3FF)) & 0x3FF)
684 } else {
685 hw
686 };
687 if n >= out.len() {
688 return Err(DecodeError::OutputFull);
689 }
690 out[n] = hw as u16;
691 n += 1;
692 }
693 if bits.overrun() {
694 return Err(DecodeError::Overrun);
695 }
696 }
697 mb += 1;
698 }
699 let announced = header.mdec_words as usize * 2;
700 let mut padded = (n + 63) & !63;
701 if padded < announced {
702 padded = (announced + 63) & !63;
703 }
704 if padded > out.len() {
705 return Err(DecodeError::OutputFull);
706 }
707 for slot in &mut out[n..padded] {
708 *slot = END_OF_BLOCK;
709 }
710 Ok(padded / 2)
711 }
712 }
713
714 fn same_as_reference(frame: &[u8], out_len: usize, mbs: u32) {
716 let mut a = std::vec![0u16; out_len];
717 let mut b = std::vec![0u16; out_len];
718 let ra = reference::decode_frame(frame, &mut a, mbs);
719 let rb = decode_frame(frame, &mut b, mbs, 1, &mut || {});
720 assert_eq!(ra, rb);
721 if let Ok(words) = ra {
722 assert_eq!(a[..words * 2], b[..words * 2]);
723 }
724 }
725
726 #[test]
727 fn rewrite_matches_reference_on_random_streams() {
728 let mut x = 0x2545_F491u32;
731 let mut next = || {
732 x ^= x << 13;
733 x ^= x >> 17;
734 x ^= x << 5;
735 x
736 };
737 let cases = if cfg!(miri) { 150 } else { 4000 };
739 for case in 0..cases {
740 let body = 8 + (next() % 400) as usize;
741 let mut frame = std::vec![0u8; HEADER_BYTES + body];
742 frame[0..2].copy_from_slice(&((next() % 64) as u16).to_le_bytes());
743 frame[2..4].copy_from_slice(&0x3800u16.to_le_bytes());
744 frame[4..6].copy_from_slice(&((next() % 64) as u16).to_le_bytes());
745 frame[6..8].copy_from_slice(&2u16.to_le_bytes());
746 for byte in &mut frame[HEADER_BYTES..] {
747 *byte = (next() & next()) as u8;
749 }
750 let out_len = [64, 256, 4096][case % 3];
751 same_as_reference(&frame, out_len, 1 + next() % 8);
752 let mut shifted = std::vec![0u8; frame.len() + 1];
754 shifted[1..].copy_from_slice(&frame);
755 same_as_reference(&shifted[1..], out_len, 4);
756 }
757 }
758
759 #[test]
763 fn rewrite_matches_reference_on_a_movie() {
764 let Some(path) = std::env::var_os("PSX_FMV_TEST_STR") else {
765 return;
766 };
767 let data = std::fs::read(path).unwrap();
768 let (size, skip) = if data.len() % 2336 == 0 && data.len() % 2048 != 0 {
769 (2336, 8)
770 } else {
771 (2048, 0)
772 };
773 let mut asm = crate::stream::FrameAssembler::new();
774 let mut buf = std::vec![0u32; 16 * 1024];
775 let mut frames = 0;
776 for sector in data.chunks_exact(size) {
777 let payload = §or[skip..skip + 2048];
778 let bytes = unsafe {
781 core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, buf.len() * 4)
782 };
783 if let Some(frame) = asm.add(payload, bytes) {
784 same_as_reference(&bytes[..frame.size as usize], 32 * 1024, 300);
785 frames += 1;
786 }
787 }
788 assert!(frames > 0, "no frames in the movie");
789 std::eprintln!("{frames} frames match");
790 }
791
792 struct Writer {
795 words: [u16; 64],
796 n: usize,
797 acc: u32,
798 used: u32,
799 }
800
801 impl Writer {
802 fn new() -> Self {
803 Writer {
804 words: [0; 64],
805 n: 0,
806 acc: 0,
807 used: 0,
808 }
809 }
810 fn put(&mut self, len: u32, value: u32) {
811 for i in (0..len).rev() {
812 self.acc = (self.acc << 1) | ((value >> i) & 1);
813 self.used += 1;
814 if self.used == 16 {
815 self.words[self.n] = self.acc as u16;
816 self.n += 1;
817 self.acc = 0;
818 self.used = 0;
819 }
820 }
821 }
822 fn frame(mut self, qscale: u16) -> ([u8; 136], usize) {
823 if self.used > 0 {
824 let pad = 16 - self.used;
825 self.put(pad, 0);
826 }
827 let mut out = [0u8; 136];
828 out[0..2].copy_from_slice(&0x0020u16.to_le_bytes());
829 out[2..4].copy_from_slice(&0x3800u16.to_le_bytes());
830 out[4..6].copy_from_slice(&qscale.to_le_bytes());
831 out[6..8].copy_from_slice(&2u16.to_le_bytes());
832 for i in 0..self.n {
833 out[8 + 2 * i..10 + 2 * i].copy_from_slice(&self.words[i].to_le_bytes());
834 }
835 (out, 8 + 2 * self.n)
836 }
837 }
838
839 fn decode(frame: &[u8], mbs: u32) -> ([u16; 256], usize) {
840 let mut out = [0u16; 256];
841 let words = decode_frame(frame, &mut out, mbs, 1, &mut || {}).unwrap();
842 (out, words)
843 }
844
845 #[test]
846 fn every_table_code_round_trips() {
847 let mut w = Writer::new();
850 w.put(10, 0x123);
851 for (i, &(len, code, _, _)) in AC_CODES.iter().enumerate().take(20) {
852 w.put(len as u32, code as u32);
853 w.put(1, (i & 1) as u32);
854 }
855 w.put(2, 0b10);
856 for _ in 1..6 {
857 w.put(10, 0x3FE); w.put(2, 0b10);
859 }
860 w.put(10, 0x1FF);
861 let (frame, len) = w.frame(5);
862 let (out, words) = decode(&frame[..len], 16);
863 assert_eq!(out[0], (5 << 10) | 0x123);
864 for (i, &(_, _, run, level)) in AC_CODES.iter().enumerate().take(20) {
865 let lv = if i & 1 == 1 {
866 (-(level as i32)) as u32 & 0x3FF
867 } else {
868 level as u32
869 };
870 assert_eq!(out[1 + i] as u32, ((run as u32) << 10) | lv, "code {i}");
871 }
872 assert_eq!(out[21], END_OF_BLOCK);
873 assert_eq!(out[22], (5 << 10) | 0x3FE);
874 assert_eq!(words, 32);
875 assert!(out[33..64].iter().all(|&h| h == END_OF_BLOCK));
876 }
877
878 #[test]
879 fn long_codes_and_escape_decode() {
880 let mut w = Writer::new();
881 w.put(10, 0);
882 let long: [usize; 4] = [23, 31, 63, 110];
884 for (k, &i) in long.iter().enumerate() {
885 let (len, code, _, _) = AC_CODES[i];
886 w.put(len as u32, code as u32);
887 w.put(1, (k & 1) as u32);
888 }
889 w.put(6, 0b000001);
890 w.put(16, (40 << 10) | 0x155);
891 w.put(2, 0b10);
892 for _ in 1..6 {
893 w.put(10, 0);
894 w.put(2, 0b10);
895 }
896 let (frame, len) = w.frame(1);
897 let (out, _) = decode(&frame[..len], 1);
898 for (k, &i) in long.iter().enumerate() {
899 let (_, _, run, level) = AC_CODES[i];
900 let lv = if k & 1 == 1 {
901 (-(level as i32)) as u32 & 0x3FF
902 } else {
903 level as u32
904 };
905 assert_eq!(out[1 + k] as u32, ((run as u32) << 10) | lv, "entry {i}");
906 }
907 assert_eq!(out[5], (40 << 10) | 0x155);
908 assert_eq!(out[6], END_OF_BLOCK);
909 }
910
911 #[test]
912 fn version_1_decodes_like_version_2() {
913 let mut w = Writer::new();
914 for block in 0..6u32 {
915 w.put(10, 0x1F0 + block);
916 let (len, code, _, _) = AC_CODES[block as usize * 7];
917 w.put(len as u32, code as u32);
918 w.put(1, block & 1);
919 w.put(2, 0b10);
920 }
921 let (mut frame, len) = w.frame(3);
922 let v2 = decode(&frame[..len], 1);
923 frame[6..8].copy_from_slice(&1u16.to_le_bytes());
924 assert_eq!(decode(&frame[..len], 1), v2);
925 }
926
927 #[test]
928 fn table_is_prefix_free_and_complete() {
929 let mut seen = 0;
931 for &(len, code, run, level) in AC_CODES.iter() {
932 let hw = ((run as u32) << 10) | level as u32;
933 let e = if len <= 8 {
934 SHORT[(code as usize) << (8 - len)]
935 } else {
936 let significant = 16 - code.leading_zeros();
937 let lz = len as u32 - significant;
938 let suffix_bits = significant - 1;
939 let suffix = code as u32 & ((1 << suffix_bits) - 1);
940 LONG[((lz - 6) * 16 + (suffix << (4 - suffix_bits))) as usize]
941 };
942 assert_eq!(e & 0xFFFF, hw, "code len {len} value {code:#x}");
943 assert_eq!((e >> 16) & 0x1F, len as u32);
944 seen += 1;
945 }
946 assert_eq!(seen, 111);
947 }
948
949 #[test]
950 fn rejects_v3_and_short_input() {
951 assert_eq!(Header::parse(&[0; 4]), Err(DecodeError::Truncated));
952 let mut f = [0u8; 16];
953 f[6] = 3;
954 let mut out = [0u16; 64];
955 assert_eq!(
956 decode_frame(&f, &mut out, 1, 1, &mut || {}),
957 Err(DecodeError::Version(3))
958 );
959 }
960}