use oxideav_core::bits::{BitReader, BitWriter};
use crate::pce::Pce;
use crate::{Error, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum IdSynEle {
Sce = 0,
Cpe = 1,
Cce = 2,
Lfe = 3,
Dse = 4,
Pce = 5,
Fil = 6,
End = 7,
}
impl IdSynEle {
pub fn from_bits(bits: u8) -> Self {
match bits & 0b111 {
0 => IdSynEle::Sce,
1 => IdSynEle::Cpe,
2 => IdSynEle::Cce,
3 => IdSynEle::Lfe,
4 => IdSynEle::Dse,
5 => IdSynEle::Pce,
6 => IdSynEle::Fil,
_ => IdSynEle::End,
}
}
pub fn name(self) -> &'static str {
match self {
IdSynEle::Sce => "SCE",
IdSynEle::Cpe => "CPE",
IdSynEle::Cce => "CCE",
IdSynEle::Lfe => "LFE",
IdSynEle::Dse => "DSE",
IdSynEle::Pce => "PCE",
IdSynEle::Fil => "FIL",
IdSynEle::End => "END",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Element {
ChannelElement {
kind: IdSynEle,
element_instance_tag: u8,
},
Fill {
payload_bytes: u32,
},
Data {
element_instance_tag: u8,
byte_align_flag: bool,
payload_bytes: u32,
},
ProgramConfig(Pce),
End,
}
pub struct Walker<'a, 'b> {
reader: &'b mut BitReader<'a>,
finished: bool,
}
impl<'a, 'b> core::fmt::Debug for Walker<'a, 'b> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Walker")
.field("finished", &self.finished)
.field("bit_position", &self.reader.bit_position())
.finish()
}
}
impl<'a, 'b> Walker<'a, 'b> {
pub fn new(reader: &'b mut BitReader<'a>) -> Self {
Self {
reader,
finished: false,
}
}
pub fn next_element(&mut self) -> Result<Option<Element>> {
self.next_element_impl(true)
}
pub fn next_element_keep_fill(&mut self) -> Result<Option<Element>> {
self.next_element_impl(false)
}
fn next_element_impl(&mut self, consume_fill: bool) -> Result<Option<Element>> {
if self.finished {
return Ok(None);
}
let id_bits = self.reader.read_u32(3).map_err(|_| Error::UnexpectedEnd)? as u8;
let id = IdSynEle::from_bits(id_bits);
match id {
IdSynEle::Sce | IdSynEle::Cpe | IdSynEle::Cce | IdSynEle::Lfe => {
let element_instance_tag =
self.reader.read_u32(4).map_err(|_| Error::UnexpectedEnd)? as u8;
Ok(Some(Element::ChannelElement {
kind: id,
element_instance_tag,
}))
}
IdSynEle::Fil => {
let payload_bytes = self.read_fill_count()?;
if consume_fill {
self.skip_bytes(payload_bytes)?;
}
Ok(Some(Element::Fill { payload_bytes }))
}
IdSynEle::Dse => {
let element_instance_tag =
self.reader.read_u32(4).map_err(|_| Error::UnexpectedEnd)? as u8;
let byte_align_flag = self.reader.read_bit().map_err(|_| Error::UnexpectedEnd)?;
let payload_bytes = self.read_data_count()?;
if byte_align_flag {
self.reader.align_to_byte();
}
self.skip_bytes(payload_bytes)?;
Ok(Some(Element::Data {
element_instance_tag,
byte_align_flag,
payload_bytes,
}))
}
IdSynEle::Pce => {
let pce = Pce::parse(self.reader, 0)?;
Ok(Some(Element::ProgramConfig(pce)))
}
IdSynEle::End => {
self.reader.align_to_byte();
self.finished = true;
Ok(Some(Element::End))
}
}
}
pub fn is_finished(&self) -> bool {
self.finished
}
fn read_fill_count(&mut self) -> Result<u32> {
let count = self.reader.read_u32(4).map_err(|_| Error::UnexpectedEnd)?;
if count == 15 {
let esc = self.reader.read_u32(8).map_err(|_| Error::UnexpectedEnd)?;
Ok(esc + 15 - 1)
} else {
Ok(count)
}
}
fn read_data_count(&mut self) -> Result<u32> {
let count = self.reader.read_u32(8).map_err(|_| Error::UnexpectedEnd)?;
if count == 255 {
let esc = self.reader.read_u32(8).map_err(|_| Error::UnexpectedEnd)?;
Ok(count + esc)
} else {
Ok(count)
}
}
fn skip_bytes(&mut self, n: u32) -> Result<()> {
let bits = n.saturating_mul(8);
self.reader.skip(bits).map_err(|_| Error::UnexpectedEnd)
}
}
pub struct FrameAssembler {
writer: BitWriter,
}
impl core::fmt::Debug for FrameAssembler {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("FrameAssembler")
.field("bit_position", &self.writer.bit_position())
.finish()
}
}
impl Default for FrameAssembler {
fn default() -> Self {
Self::new()
}
}
impl FrameAssembler {
pub fn new() -> Self {
Self {
writer: BitWriter::new(),
}
}
pub fn with_capacity(cap: usize) -> Self {
Self {
writer: BitWriter::with_capacity(cap),
}
}
pub fn bit_position(&self) -> u64 {
self.writer.bit_position()
}
pub fn push_channel_header(&mut self, kind: IdSynEle, element_instance_tag: u8) -> Result<()> {
match kind {
IdSynEle::Sce | IdSynEle::Cpe | IdSynEle::Cce | IdSynEle::Lfe => {}
_ => return Err(Error::RawDataBlockEncodeInvalid),
}
if element_instance_tag > 0x0f {
return Err(Error::RawDataBlockEncodeInvalid);
}
self.writer.write_u32(kind as u32, 3);
self.writer.write_u32(element_instance_tag as u32, 4);
Ok(())
}
pub fn push_channel_body_bits(&mut self, bits: &[u8], bit_count: u64) -> Result<()> {
if bit_count > (bits.len() as u64).saturating_mul(8) {
return Err(Error::RawDataBlockEncodeInvalid);
}
let mut remaining = bit_count;
let mut byte_idx = 0usize;
while remaining >= 8 {
self.writer.write_byte(bits[byte_idx]);
byte_idx += 1;
remaining -= 8;
}
if remaining > 0 {
let last = bits[byte_idx];
let high = (last as u32) >> (8 - remaining);
self.writer.write_u32(high, remaining as u32);
}
Ok(())
}
pub fn push_fill(&mut self, payload: &[u8]) -> Result<()> {
let n = payload.len();
if n > 269 {
return Err(Error::RawDataBlockEncodeInvalid);
}
self.writer.write_u32(IdSynEle::Fil as u32, 3);
if n < 15 {
self.writer.write_u32(n as u32, 4);
} else {
self.writer.write_u32(15, 4);
let esc = (n as u32) - 14;
self.writer.write_u32(esc, 8);
}
for &b in payload {
self.writer.write_byte(b);
}
Ok(())
}
pub fn push_data(
&mut self,
element_instance_tag: u8,
byte_align_flag: bool,
payload: &[u8],
) -> Result<()> {
if element_instance_tag > 0x0f {
return Err(Error::RawDataBlockEncodeInvalid);
}
let n = payload.len();
if n > 510 {
return Err(Error::RawDataBlockEncodeInvalid);
}
self.writer.write_u32(IdSynEle::Dse as u32, 3);
self.writer.write_u32(element_instance_tag as u32, 4);
self.writer.write_bit(byte_align_flag);
if n < 255 {
self.writer.write_u32(n as u32, 8);
} else {
self.writer.write_u32(255, 8);
let esc = (n as u32) - 255;
self.writer.write_u32(esc, 8);
}
if byte_align_flag {
self.writer.align_to_byte();
}
for &b in payload {
self.writer.write_byte(b);
}
Ok(())
}
pub fn push_pce(&mut self, pce: &Pce) -> Result<()> {
self.writer.write_u32(IdSynEle::Pce as u32, 3);
pce.write(&mut self.writer, 0)
}
pub fn push_end(mut self) -> Vec<u8> {
self.writer.write_u32(IdSynEle::End as u32, 3);
self.writer.align_to_byte();
self.writer.finish()
}
}