use super::bits::BitReader;
use super::error::{Error, Result};
use super::ics::IcsInfo;
pub const ZERO_HCB: u8 = 0;
pub const ESC_HCB: u8 = 11;
pub const NOISE_HCB: u8 = 13;
pub const INTENSITY_HCB2: u8 = 14;
pub const INTENSITY_HCB: u8 = 15;
#[derive(Debug, Clone, Default)]
pub struct SectionData {
pub sfb_cb: Vec<Vec<u8>>,
}
fn fit_u8(rows: &mut Vec<Vec<u8>>, groups: usize, n: usize) {
if rows.len() < groups {
rows.resize(groups, Vec::new());
}
for row in rows.iter_mut().take(groups) {
row.clear();
row.resize(n, 0);
}
}
impl SectionData {
#[cfg(test)]
pub fn parse(br: &mut BitReader<'_>, ics: &IcsInfo) -> Result<Self> {
let mut out = Self::default();
out.parse_into(br, ics)?;
Ok(out)
}
pub fn parse_into(&mut self, br: &mut BitReader<'_>, ics: &IcsInfo) -> Result<()> {
let esc = if ics.window_sequence.is_eight_short() {
7u32
} else {
31
};
let incr_bits = if ics.window_sequence.is_eight_short() {
3
} else {
5
};
let groups = ics.num_window_groups as usize;
let max_sfb = ics.max_sfb as usize;
fit_u8(&mut self.sfb_cb, groups, max_sfb);
for g in 0..groups {
let cb = &mut self.sfb_cb[g];
let mut k = 0u32;
while k < u32::from(ics.max_sfb) {
let sect_cb = br.read(4)? as u8;
if sect_cb == 12 {
return Err(Error::InvalidCodebook(sect_cb));
}
let mut sect_len = 0u32;
loop {
let incr = br.read(incr_bits)?;
sect_len += incr;
if incr != esc {
break;
}
}
if k + sect_len > u32::from(ics.max_sfb) {
return Err(Error::SectionDataOverrun);
}
for sfb in k..k + sect_len {
cb[sfb as usize] = sect_cb;
}
k += sect_len;
}
}
Ok(())
}
}
#[must_use]
pub fn is_intensity(cb: u8) -> bool {
cb == INTENSITY_HCB || cb == INTENSITY_HCB2
}
#[must_use]
pub fn is_noise(cb: u8) -> bool {
cb == NOISE_HCB
}
#[must_use]
pub fn has_spectral(cb: u8) -> bool {
(1..=ESC_HCB).contains(&cb)
}