use crate::{dev::*, records::all::{ActorReference, Cell, Landscape, NavigationMesh, Reference}};
#[derive(Debug)]
pub struct CellEntry {
pub cell: Cell,
pub children: Option<CellChildren>
}
impl Parse<&[u8]> for CellEntry {
fn parse(i: &[u8]) -> IResult<&[u8], Self, nom::error::Error<&[u8]>> {
let (i, cell) = Cell::parse(i)?;
if i.len() < 4 {
return Ok((i, Self { cell, children: None }) )
}
let (_, next_id) = FourCC::parse(i)?;
if &next_id.0 != GRUP {
return Ok((i, Self { cell, children: None }) )
}
let (_, next_header) = GroupHeader::parse(i)?;
match next_header.label {
GroupLabel::CellChildren(_) => {
let (i, children) = CellChildren::parse(i)?;
Ok((i, Self { cell, children: Some(children) }) )
}
_ => {
Ok((i, Self { cell, children: None }) )
}
}
}
}
#[derive(Debug)]
pub struct CellChildren {
pub header: GroupHeader,
pub persistent_children: Option<CellPersistentChildren>,
pub temporary_children: Option<CellTemporaryChildren>
}
impl Parse<&[u8]> for CellChildren {
fn parse(i: &[u8]) -> IResult<&[u8], Self, nom::error::Error<&[u8]>> {
let (i, (header, raw)) = alloc_group(i)?;
let mut persistent_children = None;
let mut temporary_children = None;
#[cfg(debug_assertions)]
match header.label {
GroupLabel::CellChildren(_) => { }
_ => { panic!("CellChildren::parse encountered wrong group type: {:?}", header.label) }
}
let (_, next_header) = GroupHeader::parse(raw)?;
match next_header.label {
GroupLabel::CellPersistentChildren(_) => {
let (raw, pc) = CellPersistentChildren::parse(raw)?;
persistent_children = Some(pc);
if !raw.is_empty() {
let (_, tc) = CellTemporaryChildren::parse(raw)?;
temporary_children = Some(tc);
}
}
GroupLabel::CellTemporaryChildren(_) => {
let (raw, tc) = CellTemporaryChildren::parse(raw)?;
temporary_children = Some(tc);
#[cfg(debug_assertions)]
if !raw.is_empty() {
panic!("Warning: Extra data found after CellTemporaryChildren in CellChildren group");
}
}
_ => { panic!("Encountered wrong group type in CellChildren::parse") }
}
Ok((i, Self { header, persistent_children, temporary_children }) )
}
}
#[derive(Debug)]
pub struct CellPersistentChildren {
pub header: GroupHeader,
pub children: Vec<CellChildItem>,
}
impl Parse<&[u8]> for CellPersistentChildren {
fn parse(i: &[u8]) -> IResult<&[u8], Self, nom::error::Error<&[u8]>> {
let (i, (header, raw)) = alloc_group(i)?;
#[cfg(debug_assertions)]
match header.label {
GroupLabel::CellPersistentChildren(_) => { }
_ => { panic!("CellPersistentChildren::parse encountered wrong group type: {:?}", header.label) }
}
let (_, children) = many0(CellChildItem::parse)(raw)?;
Ok((i, Self { header, children }) )
}
}
#[derive(Debug)]
pub struct CellTemporaryChildren {
pub header: GroupHeader,
pub children: Vec<CellChildItem>
}
impl Parse<&[u8]> for CellTemporaryChildren {
fn parse(i: &[u8]) -> IResult<&[u8], Self, nom::error::Error<&[u8]>> {
let (i, (header, raw)) = alloc_group(i)?;
#[cfg(debug_assertions)]
match header.label {
GroupLabel::CellTemporaryChildren(_) => { }
_ => { panic!("CellTemporaryChildren::parse encountered wrong group type: {:?}", header.label) }
}
let (_, children) = many0(CellChildItem::parse)(raw)?;
Ok((i, Self { header, children }) )
}
}
#[derive(Debug)]
pub enum CellChildItem {
ItemReference(Reference),
Landscape(Landscape),
ActorReference(ActorReference),
NavigationMesh(NavigationMesh)
}
impl Parse<&[u8]> for CellChildItem {
fn parse(i: &[u8]) -> IResult<&[u8], Self, nom::error::Error<&[u8]>> {
let (i, header) = RecordHeader::parse(i)?;
match &header.iden.0{
b"REFR" => {
let (i, reference) = Reference::parse(i)?;
Ok((i, CellChildItem::ItemReference(reference)))
}
b"LAND" => {
let (i, landscape) = Landscape::parse(i)?;
Ok((i, CellChildItem::Landscape(landscape)))
}
b"ACHR" => {
let (i, actor_ref) = ActorReference::parse(i)?;
Ok((i, CellChildItem::ActorReference(actor_ref)))
}
b"NAVM" => {
let (i, nav_mesh) = NavigationMesh::parse(i)?;
Ok((i, CellChildItem::NavigationMesh(nav_mesh)))
}
_ => {
panic!("CellChildItem::parse encountered unknown record type: {:?}", header.iden);
}
}
}
}