use std::io::{self, SeekFrom};
use crate::{stream::BinStream, Error};
use super::{Bin, BinObject};
use byteorder::{ReadBytesExt as _, LE};
use indexmap::IndexMap;
use ltk_hash::{BinHash, ReadBytesExt as _};
impl Bin {
pub fn from_reader<R: io::Read + std::io::Seek + ?Sized>(
reader: &mut R,
) -> Result<Self, Error> {
BinStream::mount(reader)?.into_bin()
}
}
pub(crate) fn read_objects<R: io::Read + io::Seek + ?Sized>(
reader: &mut R,
) -> Result<(IndexMap<BinHash, BinObject>, bool), Error> {
let count = reader.read_u32::<LE>()? as usize;
let mut classes = Vec::with_capacity(count);
for _ in 0..count {
classes.push(reader.read_bin_hash::<LE>()?);
}
let start = reader.stream_position()?;
let mut objects = IndexMap::with_capacity(count);
match try_read_objects(reader, &classes, &mut objects, false) {
Ok(()) => Ok((objects, false)),
Err(Error::InvalidPropertyTypePrimitive(kind)) => {
log::warn!("Invalid prop type {kind}. Trying reading objects as legacy.");
reader.seek(SeekFrom::Start(start))?;
try_read_objects(reader, &classes, &mut objects, true)?;
Ok((objects, true))
}
Err(e) => Err(e),
}
}
fn try_read_objects<R: io::Read + io::Seek + ?Sized>(
reader: &mut R,
classes: &[BinHash],
objects: &mut IndexMap<BinHash, BinObject>,
legacy: bool,
) -> Result<(), Error> {
objects.clear();
for &class_hash in classes {
let object = BinObject::from_reader(reader, class_hash, legacy)?;
objects.insert(object.path_hash, object);
}
Ok(())
}