use hff_core::{ByteOrder, Chunk, Header, Result, Table, NE, OP};
use std::{io::Read, mem::size_of};
mod read_seek;
pub use read_seek::ReadSeek;
mod hff_cache;
pub use hff_cache::ChunkCache;
mod hff;
pub use hff::Hff;
mod table_view;
pub use table_view::TableView;
mod chunk_view;
pub use chunk_view::ChunkView;
mod chunk_iter;
pub use chunk_iter::ChunkIter;
mod table_iter;
pub use table_iter::TableIter;
mod depth_first_iter;
pub use depth_first_iter::DepthFirstIter;
pub fn read_stream(reader: &mut dyn Read) -> Result<Hff> {
let header = Header::read(reader)?;
let (tables, chunks) = if header.is_native_endian() {
(
read_tables::<NE>(reader, header.table_count())?,
read_chunks::<NE>(reader, header.chunk_count())?,
)
} else {
(
read_tables::<OP>(reader, header.table_count())?,
read_chunks::<OP>(reader, header.chunk_count())?,
)
};
Ok(Hff::new(header, tables, chunks))
}
pub fn read_stream_full(reader: &mut dyn Read) -> Result<(Hff, ChunkCache)> {
let hff = read_stream(reader)?;
let mut buffer = vec![];
reader.read_to_end(&mut buffer)?;
let offset = hff.offset_to_data();
Ok((hff, ChunkCache::new(offset, buffer)))
}
fn read_tables<E: ByteOrder>(reader: &mut dyn Read, count: u32) -> Result<Vec<Table>> {
if count > 0 {
let mut buffer = vec![0; count as usize * size_of::<Table>()];
reader.read_exact(&mut buffer.as_mut_slice())?;
let mut tables = vec![];
let reader: &mut dyn Read = &mut buffer.as_slice();
for _ in 0..count {
let table = Table::read::<E>(reader)?;
tables.push(table);
}
Ok(tables)
} else {
Ok(vec![])
}
}
fn read_chunks<E: ByteOrder>(reader: &mut dyn Read, count: u32) -> Result<Vec<Chunk>> {
if count > 0 {
let mut buffer = vec![0; count as usize * size_of::<Chunk>()];
reader.read_exact(&mut buffer.as_mut_slice())?;
let mut chunks = vec![];
let reader: &mut dyn Read = &mut buffer.as_slice();
for _ in 0..count {
let chunk = Chunk::read::<E>(reader)?;
chunks.push(chunk);
}
Ok(chunks)
} else {
Ok(vec![])
}
}