#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::{MuxCfg, latm_value, read_frame_len, skip_mux_tail};
use crate::engine::bits::{BitReader, BitWriter};
use crate::engine::crc::stream_mux_config_crc;
use crate::engine::error::Error;
fn push_bits(bits: &mut Vec<bool>, value: u32, n: u32) {
for i in (0..n).rev() {
bits.push((value >> i) & 1 != 0);
}
}
fn bits_to_bytes(bits: &[bool]) -> Vec<u8> {
let mut w = BitWriter::new();
for &b in bits {
w.write_bit(b);
}
w.finish()
}
fn mux_config_bits() -> Vec<bool> {
let mut b = Vec::new();
push_bits(&mut b, 0, 1); push_bits(&mut b, 1, 1); push_bits(&mut b, 0, 6); push_bits(&mut b, 0, 4); push_bits(&mut b, 0, 3); push_bits(&mut b, 2, 5); push_bits(&mut b, 4, 4); push_bits(&mut b, 2, 4); push_bits(&mut b, 0, 3); push_bits(&mut b, 1, 3); push_bits(&mut b, 0, 9); push_bits(&mut b, 0, 1); b
}
#[test]
fn mux_version_a_reserved_and_program_layer() -> Result<(), Error> {
let mut w = BitWriter::new();
w.write_bit(true);
w.write_bit(true);
let bytes = w.finish();
let mut br = BitReader::new(&bytes);
assert!(matches!(
MuxCfg::parse(&mut br),
Err(Error::LatmAudioMuxVersionAReserved)
));
let mut w = BitWriter::new();
w.write_bit(false);
w.write_bit(false);
w.write(0, 6);
w.write(1, 4);
w.write(0, 3);
let bytes = w.finish();
let mut br = BitReader::new(&bytes);
assert!(matches!(
MuxCfg::parse(&mut br),
Err(Error::LatmConfigOutOfRange)
));
Ok(())
}
#[test]
fn frame_len_types_and_mux_tail_and_latm_value() -> Result<(), Error> {
let mut w = BitWriter::new();
w.write(0, 8);
let bytes = w.finish();
let mut br = BitReader::new(&bytes);
assert_eq!(read_frame_len(&mut br, 0)?, 0);
let mut w = BitWriter::new();
w.write(8, 9);
let bytes = w.finish();
let mut br = BitReader::new(&bytes);
assert_eq!(read_frame_len(&mut br, 1)?, 8);
let mut br = BitReader::new(&[0xFF]);
assert!(read_frame_len(&mut br, 2).is_err());
let mut b = Vec::new();
push_bits(&mut b, 1, 1); push_bits(&mut b, 0, 1); push_bits(&mut b, 0, 8); push_bits(&mut b, 0, 1); let crc = u32::from(stream_mux_config_crc(&b));
b.push(true); push_bits(&mut b, crc, 8);
let bytes = bits_to_bytes(&b);
let mut br = BitReader::new(&bytes);
skip_mux_tail(&mut br, 0)?;
let mut b = Vec::new();
push_bits(&mut b, 1, 1);
push_bits(&mut b, 1, 1); b.push(false); push_bits(&mut b, 1, 8);
b.push(false); let bytes = bits_to_bytes(&b);
let mut br = BitReader::new(&bytes);
skip_mux_tail(&mut br, 0)?;
let mut w = BitWriter::new();
w.write(1, 8);
w.write_bit(true);
w.write(2, 8);
w.write_bit(false);
let bytes = w.finish();
let mut br = BitReader::new(&bytes);
assert_eq!(latm_value(&mut br)?, (1 << 8) | 2);
Ok(())
}
#[test]
fn mux_cfg_crc_absent_parses() -> Result<(), Error> {
let mut b = mux_config_bits();
b.push(false); let bytes = bits_to_bytes(&b);
let mut br = BitReader::new(&bytes);
let cfg = MuxCfg::parse(&mut br)?;
assert_eq!(cfg.frame_length_type, 1);
Ok(())
}
#[test]
fn mux_cfg_crc_present_valid_parses() -> Result<(), Error> {
let mut b = mux_config_bits();
let crc = u32::from(stream_mux_config_crc(&b));
b.push(true); push_bits(&mut b, crc, 8);
let bytes = bits_to_bytes(&b);
let mut br = BitReader::new(&bytes);
let cfg = MuxCfg::parse(&mut br)?;
assert_eq!(cfg.frame_length_type, 1);
Ok(())
}
#[test]
fn mux_cfg_crc_present_corrupt_rejected() {
let mut b = mux_config_bits();
let crc = u32::from(stream_mux_config_crc(&b)) ^ 0xFF;
b.push(true); push_bits(&mut b, crc, 8);
let bytes = bits_to_bytes(&b);
let mut br = BitReader::new(&bytes);
assert!(matches!(
MuxCfg::parse(&mut br),
Err(Error::LatmCrcMismatch)
));
}