use core::fmt::{Display, Formatter, Result as FmtResult};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct ChunkID {
pub id: [u8; 4],
}
impl AsRef<[u8]> for ChunkID {
#[inline]
fn as_ref(&self) -> &[u8] {
&self.id
}
}
impl Display for ChunkID {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match core::str::from_utf8(&self.id) {
Ok(s) => write!(f, "{s}"),
Err(e) => {
writeln!(f, "ChunkID Display error: {e}")?;
write!(
f,
"0x{:02X}{:02X}{:02X}{:02X}",
self.id[0], self.id[1], self.id[2], self.id[3]
)
}
}
}
}
impl From<&[u8; 4]> for ChunkID {
fn from(value: &[u8; 4]) -> Self {
ChunkID { id: *value }
}
}
impl ChunkID {
#[inline]
pub const fn new(id: &[u8; 4]) -> Self {
ChunkID { id: *id }
}
#[inline]
pub const fn as_bytes(&self) -> &[u8; 4] {
&self.id
}
#[inline]
pub fn as_str(&self) -> Option<&str> {
core::str::from_utf8(&self.id).ok()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChunkDesc {
pub id: ChunkID,
pub offset: usize,
pub logical_size: usize,
pub total_size: usize,
}
impl ChunkDesc {
#[inline]
pub const fn len(&self) -> usize {
self.logical_size
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.logical_size == 0
}
#[inline]
pub const fn data_range(&self) -> std::ops::Range<usize> {
let start = self.offset + 8; start..(start + self.logical_size)
}
#[inline]
pub const fn total_size(&self) -> usize {
self.total_size
}
}
impl Display for ChunkDesc {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(
f,
"Chunk ID: {}, Offset: {}, Logical Size: {}, Total Size: {}",
self.id, self.offset, self.logical_size, self.total_size
)
}
}
pub trait ChunkAccessor {
fn get_chunk(&self, chunk_id: &ChunkID) -> Option<ChunkDesc>;
}
pub const RIFF_CHUNK: ChunkID = ChunkID::new(b"RIFF");
pub const WAVE_CHUNK: ChunkID = ChunkID::new(b"WAVE");
pub const FMT_CHUNK: ChunkID = ChunkID::new(b"fmt ");
pub const DATA_CHUNK: ChunkID = ChunkID::new(b"data");
pub const FACT_CHUNK: ChunkID = ChunkID::new(b"fact");
pub const LIST_CHUNK: ChunkID = ChunkID::new(b"LIST");
pub const CUE_CHUNK: ChunkID = ChunkID::new(b"cue ");