use crate::dev::*;
#[derive(Debug)]
pub struct Field<T> {
pub header: FieldHeader,
pub data: T,
}
impl<T> Parse<&[u8]> for Field<T> where T: for<'esm> Parse<&'esm [u8]> {
fn parse(i: &[u8]) -> IResult<&[u8], Self, nom::error::Error<&[u8]>> {
let (i, (header, raw)) = alloc_field(i)?;
let (_, data) = T::parse(raw)?;
Ok((i, Field { header, data }))
}
}
#[derive(Debug, NomLE, Clone, Copy)]
pub struct FieldHeader16 {
pub iden: FourCC,
pub size: u16, }
#[derive(Debug, NomLE, Clone, Copy)]
pub struct FieldHeader32 {
_size_iden: FourCC, _skipped_size: u16, pub size: u32, pub iden: FourCC, _skipped_size2: u16, }
#[derive(Debug, Clone, Copy)]
pub enum FieldHeader {
Normal(FieldHeader16),
Large(FieldHeader32),
}
impl FieldHeader {
pub fn size(&self) -> usize {
match self {
FieldHeader::Normal(h) => h.size as usize,
FieldHeader::Large(h) => h.size as usize,
}
}
pub fn iden(&self) -> &FourCC {
match self {
FieldHeader::Normal(h) => &h.iden,
FieldHeader::Large(h) => &h.iden,
}
}
}
impl Parse<&[u8]> for FieldHeader {
fn parse(i: &[u8]) -> IResult<&[u8], Self, nom::error::Error<&[u8]>> {
let (orig, iden) = FourCC::parse(i)?;
if &iden.0 == b"XXXX" {
let (i, size) = le_u16(orig)?;
let (i, real_size) = le_u32(i)?;
let (i, real_iden) = FourCC::parse(i)?;
let (i, zero_size) = le_u16(i)?;
Ok((i, FieldHeader::Large(FieldHeader32 {
_size_iden: iden,
_skipped_size: size,
size: real_size,
iden: real_iden,
_skipped_size2: zero_size,
})))
} else {
let (i, size) = le_u16(orig)?;
Ok((i, FieldHeader::Normal(FieldHeader16 { iden, size })))
}
}
}
pub struct RawField<'esm> {
pub header: FieldHeader,
pub data: &'esm [u8],
}
impl<'esm> Parse<&'esm [u8]> for RawField<'esm> {
fn parse(i: &'esm [u8]) -> IResult<&'esm [u8], Self, nom::error::Error<&'esm [u8]>> {
let (i, (header, data)) = alloc_field(i)?;
Ok((i, RawField { header, data }))
}
}
impl std::fmt::Debug for RawField<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"RawField {{ header: {:?}, data: [verbose bytes]",
self.header
)
}
}
pub fn alloc_field(i: &[u8]) -> IResult<&[u8], (FieldHeader, &[u8]), nom::error::Error<&[u8]>> {
let (i, header) = FieldHeader::parse(i)?;
let size = match &header {
FieldHeader::Normal(h) => h.size as usize,
FieldHeader::Large(h) => h.size as usize,
};
let (i, data) = take(size)(i)?;
Ok((i, (header, data)))
}
pub type UnusedData = EmptyParser;
#[derive(Debug, NomLE)]
pub struct EmptyParser;