use crate::ape::tag::error::ApeTagParseError;
use crate::error::SizeMismatchError;
use crate::util::io::SeekStreamLen;
use std::io::{Read, Seek, SeekFrom};
use std::ops::Neg;
use byteorder::{LittleEndian, ReadBytesExt};
#[derive(Copy, Clone)]
pub(crate) struct ApeHeader {
pub(crate) size: u32,
pub(crate) item_count: u32,
}
pub(crate) fn read_ape_header<R>(data: &mut R, footer: bool) -> Result<ApeHeader, ApeTagParseError>
where
R: Read + Seek,
{
let version = data.read_u32::<LittleEndian>()?;
let mut size = data.read_u32::<LittleEndian>()?;
if size < 32 {
return Err(SizeMismatchError.into());
}
let item_count = data.read_u32::<LittleEndian>()?;
if footer {
data.seek(SeekFrom::Current(i64::from(size - 12).neg()))?;
} else {
data.seek(SeekFrom::Current(12))?;
}
if version == 2000 {
size = size.saturating_add(32);
}
if u64::from(size) > data.stream_len_hack()? {
return Err(SizeMismatchError.into());
}
Ok(ApeHeader { size, item_count })
}