1use crate::{ReadSeek, StdReader};
2use hff_core::{
3 byteorder::ReadBytesExt,
4 read::{Hff, Inspection},
5 ByteOrder, Chunk, ChunkCache, Ecc, Endian, Error, Header, Result, Table, Version, BE, LE, NE,
6 OP,
7};
8use std::{io::Read, mem::size_of};
9
10pub fn open(mut source: impl ReadSeek + 'static) -> Result<Hff<StdReader>> {
13 let (header, tables, chunks) = read_hff(&mut source)?;
14 Ok(Hff::new(StdReader::new(source), header, tables, chunks))
15}
16
17pub fn read(source: &mut dyn Read) -> Result<Hff<ChunkCache>> {
19 let (header, tables, chunks, cache) = read_hff_full(source)?;
20 Ok(Hff::new(cache, header, tables, chunks))
21}
22
23pub fn inspect(source: &mut dyn Read) -> Result<Hff<Inspection>> {
27 let (header, tables, chunks) = read_hff(source)?;
28 Ok(Hff::new(Inspection, header, tables, chunks))
29}
30
31pub(super) fn read_hff(reader: &mut dyn Read) -> Result<(Header, Vec<Table>, Vec<Chunk>)> {
34 let header = read_header(reader)?;
36 let (tables, chunks) = if header.is_native_endian() {
37 (
38 read_tables::<NE>(reader, header.table_count())?,
39 read_chunks::<NE>(reader, header.chunk_count())?,
40 )
41 } else {
42 (
43 read_tables::<OP>(reader, header.table_count())?,
44 read_chunks::<OP>(reader, header.chunk_count())?,
45 )
46 };
47
48 Ok((header, tables, chunks))
49}
50
51fn read_hff_full(reader: &mut dyn Read) -> Result<(Header, Vec<Table>, Vec<Chunk>, ChunkCache)> {
52 let (header, tables, chunks) = read_hff(reader)?;
53
54 let mut buffer = vec![];
55 reader.read_to_end(&mut buffer)?;
56
57 let offset = size_of::<Header>()
58 + (size_of::<Table>() * tables.len())
59 + (size_of::<Chunk>() * chunks.len());
60 let cache = ChunkCache::new(offset, buffer);
61
62 Ok((header, tables, chunks, cache))
63}
64
65fn read_header(reader: &mut dyn Read) -> Result<Header> {
67 let mut magic = [0_u8; 8];
68 reader.read_exact(&mut magic)?;
69
70 match Ecc::HFF_MAGIC.endian(magic.into()) {
75 Some(endian) => match endian {
76 Endian::Little => Ok(Header::with(
77 magic.into(),
78 Version::read::<LE>(reader)?,
79 reader.read_u32::<LE>()?,
80 Ecc::read::<LE>(reader)?,
81 reader.read_u32::<LE>()?,
82 reader.read_u32::<LE>()?,
83 )),
84 Endian::Big => Ok(Header::with(
85 magic.into(),
86 Version::read::<BE>(reader)?,
87 reader.read_u32::<BE>()?,
88 Ecc::read::<BE>(reader)?,
89 reader.read_u32::<BE>()?,
90 reader.read_u32::<BE>()?,
91 )),
92 },
93 None => Err(Error::Invalid("Not an HFF file.".into())),
94 }
95}
96
97fn read_tables<E: ByteOrder>(reader: &mut dyn Read, count: u32) -> Result<Vec<Table>> {
98 if count > 0 {
99 let mut buffer = vec![0; count as usize * size_of::<Table>()];
101 reader.read_exact(&mut buffer.as_mut_slice())?;
102
103 let mut tables = vec![];
105 let reader: &mut dyn Read = &mut buffer.as_slice();
106 for _ in 0..count {
107 let table = Table::read::<E>(reader)?;
108 tables.push(table);
109 }
110
111 Ok(tables)
112 } else {
113 Ok(vec![])
115 }
116}
117
118fn read_chunks<E: ByteOrder>(reader: &mut dyn Read, count: u32) -> Result<Vec<Chunk>> {
119 if count > 0 {
120 let mut buffer = vec![0; count as usize * size_of::<Chunk>()];
122 reader.read_exact(&mut buffer.as_mut_slice())?;
123
124 let mut chunks = vec![];
126 let reader: &mut dyn Read = &mut buffer.as_slice();
127 for _ in 0..count {
128 let chunk = Chunk::read::<E>(reader)?;
129 chunks.push(chunk);
130 }
131 Ok(chunks)
132 } else {
133 Ok(vec![])
136 }
137}