//! Map file entry data. use crate::{bin::*, err::*, image::{self, pict}, map}; use super::{entr, head}; use std::collections::BTreeMap; /// Reads all chunks in an entry. pub fn read(head: &head::Header, b: &[u8]) -> ResultS { let mut data = EntryData::default(); let old = head.old_data(); let rd_cminf = if old {map::minf::read_old} else {map::minf::read}; let rd_csids = if old {map::sids::read_old} else {map::sids::read}; let rd_cpoly = if old {map::poly::read_old} else {map::poly::read}; let rd_clite = if old {map::lite::read_old} else {map::lite::read}; let mut p = 0; while p < b.len() { read_data! { endian: BIG, buf: b, size: head.size_chunk(), start: p, data { let iden = Ident[0]; let size = u32[8] usize; } } let beg = p + head.size_chunk(); let end = beg + size; let buf = ok!(b.get(beg..end), "not enough data")?; match &iden.0 { b"EPNT" => data.epnt = Some(rd_array(buf, map::epnt::read)?), b"FXpx" => data.fxpx = Some(rd_array(buf, map::fxpx::read)?), b"LINS" => data.lins = Some(rd_array(buf, map::lins::read)?), b"LITE" => data.lite = Some(rd_array(buf, rd_clite)?), b"MNpx" => data.mnpx = Some(rd_array(buf, map::mnpx::read)?), b"Minf" => data.minf = Some(rd_cminf(buf)?), b"NAME" => data.name = Some(rd_array(buf, map::name::read)?), b"NOTE" => data.note = Some(rd_array(buf, map::note::read)?), b"OBJS" => data.objs = Some(rd_array(buf, map::objs::read)?), b"PICT" => data.pict = Some(pict::read(buf)?), b"PNTS" => data.pnts = Some(rd_array(buf, map::pnts::read)?), b"POLY" => data.poly = Some(rd_array(buf, rd_cpoly)?), b"PRpx" => data.prpx = Some(rd_array(buf, map::prpx::read)?), b"PXpx" => data.pxpx = Some(rd_array(buf, map::pxpx::read)?), b"SIDS" => data.sids = Some(rd_array(buf, rd_csids)?), b"WPpx" => data.wppx = Some(rd_array(buf, map::wppx::read)?), b"ambi" => data.ambi = Some(rd_array(buf, map::ambi::read)?), b"bonk" => data.bonk = Some(rd_array(buf, map::bonk::read)?), b"iidx" => data.iidx = Some(rd_array(buf, map::iidx::read)?), b"medi" => data.medi = Some(rd_array(buf, map::medi::read)?), b"plac" => data.plac = Some(rd_array(buf, map::plac::read)?), b"plat" => data.plat = Some(rd_array(buf, map::plat::read)?), b"term" => data.term = Some(rd_array(buf, map::term::read)?), _ => data.unkn.push((iden, buf.to_vec())), } p = end; } Ok(data) } /// Reads all of the data from an entry map. pub fn read_all(head: &head::Header, map: &entr::EntryMap<'_>) -> ResultS { let mut data_map = EntryDataMap::new(); for (&index, entry) in map { data_map.insert(index, read(head, entry.data)?); } Ok(data_map) } impl EntryData { pub fn get_type(&self) -> EntryType { if self.has_minf() { EntryType::Map } else if self.has_fxpx() || self.has_mnpx() || self.has_prpx() || self.has_pxpx() || self.has_wppx() { EntryType::Physics } else if self.has_pict() { EntryType::Image } else { EntryType::Other } } pub fn has_epnt(&self) -> bool {self.epnt.is_some()} pub fn has_fxpx(&self) -> bool {self.fxpx.is_some()} pub fn has_lins(&self) -> bool {self.lins.is_some()} pub fn has_lite(&self) -> bool {self.lite.is_some()} pub fn has_mnpx(&self) -> bool {self.mnpx.is_some()} pub fn has_minf(&self) -> bool {self.minf.is_some()} pub fn has_name(&self) -> bool {self.name.is_some()} pub fn has_note(&self) -> bool {self.note.is_some()} pub fn has_objs(&self) -> bool {self.objs.is_some()} pub fn has_pict(&self) -> bool {self.pict.is_some()} pub fn has_pnts(&self) -> bool {self.pnts.is_some()} pub fn has_poly(&self) -> bool {self.poly.is_some()} pub fn has_prpx(&self) -> bool {self.prpx.is_some()} pub fn has_pxpx(&self) -> bool {self.pxpx.is_some()} pub fn has_sids(&self) -> bool {self.sids.is_some()} pub fn has_wppx(&self) -> bool {self.wppx.is_some()} pub fn has_ambi(&self) -> bool {self.ambi.is_some()} pub fn has_bonk(&self) -> bool {self.bonk.is_some()} pub fn has_iidx(&self) -> bool {self.iidx.is_some()} pub fn has_medi(&self) -> bool {self.medi.is_some()} pub fn has_plac(&self) -> bool {self.plac.is_some()} pub fn has_plat(&self) -> bool {self.plat.is_some()} pub fn has_term(&self) -> bool {self.term.is_some()} pub fn num_unknown(&self) -> usize {self.unkn.len()} pub fn len(&self) -> usize { self.num_unknown() + usize::from(self.has_epnt()) + usize::from(self.has_fxpx()) + usize::from(self.has_lins()) + usize::from(self.has_lite()) + usize::from(self.has_mnpx()) + usize::from(self.has_minf()) + usize::from(self.has_name()) + usize::from(self.has_note()) + usize::from(self.has_objs()) + usize::from(self.has_pict()) + usize::from(self.has_pnts()) + usize::from(self.has_poly()) + usize::from(self.has_prpx()) + usize::from(self.has_pxpx()) + usize::from(self.has_sids()) + usize::from(self.has_wppx()) + usize::from(self.has_ambi()) + usize::from(self.has_bonk()) + usize::from(self.has_iidx()) + usize::from(self.has_medi()) + usize::from(self.has_plac()) + usize::from(self.has_plat()) } pub fn is_empty(&self) -> bool {self.len() == 0} } /// The abstract type of an entry. pub enum EntryType { Other, Map, Image, Physics, } /// The loaded data of a Map file entry. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Debug, Default, Eq, PartialEq)] pub struct EntryData { /** `EPNT` chunk data. */ pub epnt: Option>, /** `FXpx` chunk data. */ pub fxpx: Option>, /** `LINS` chunk data. */ pub lins: Option>, /** `LITE` chunk data. */ pub lite: Option>, /** `MNpx` chunk data. */ pub mnpx: Option>, /** `Minf` chunk data. */ pub minf: Option, /** `NAME` chunk data. */ pub name: Option>, /** `NOTE` chunk data. */ pub note: Option>, /** `OBJS` chunk data. */ pub objs: Option>, /** `PICT` chunk data. */ pub pict: Option, /** `PNTS` chunk data. */ pub pnts: Option>, /** `POLY` chunk data. */ pub poly: Option>, /** `PRpx` chunk data. */ pub prpx: Option>, /** `PXpx` chunk data. */ pub pxpx: Option>, /** `SIDS` chunk data. */ pub sids: Option>, /** `WPpx` chunk data. */ pub wppx: Option>, /** `ambi` chunk data. */ pub ambi: Option>, /** `bonk` chunk data. */ pub bonk: Option>, /** `iidx` chunk data. */ pub iidx: Option>, /** `medi` chunk data. */ pub medi: Option>, /** `plac` chunk data. */ pub plac: Option>, /** `plat` chunk data. */ pub plat: Option>, /** `term` chunk data. */ pub term: Option>, pub unkn: Vec<(Ident, Vec)>, } /// A map of indexed entries. pub type EntryDataMap = BTreeMap; // EOF