use std::ffi::CString; use std::fs::read; use std::io::Cursor; use binrw::binrw; use crate::gamedata::MemoryBuffer; use binrw::BinRead; #[binrw] #[brw(magic = b"FileInfo")] #[derive(Debug)] pub struct FileInfo { #[brw(pad_before = 16)] #[br(ignore)] #[bw(calc = 1024)] unknown : i32, #[br(temp)] #[bw(calc = (entries.len() * 96) as i32)] entries_size : i32, #[brw(pad_before = 992)] #[br(count = entries_size / 96)] entries : Vec } #[binrw] #[derive(Debug)] pub struct FIINEntry { file_size : i32, #[brw(pad_before = 4)] #[br(count = 64)] #[br(map = | x: Vec < u8 > | String::from_utf8(x).unwrap())] #[bw(map = | x : &String | x.as_bytes().to_vec())] #[bw(pad_size_to = 64)] file_name: String, #[br(count = 24)] #[bw(pad_size_to = 24)] sha1 : Vec } impl FileInfo { pub fn from_existing(buffer : &MemoryBuffer) -> Option { let mut cursor = Cursor::new(buffer); Some(FileInfo::read(&mut cursor).ok()?) } pub fn new(file_names : Vec<&str>) -> Option { let mut entries = vec![]; for name in file_names { let file = &read(&name).expect("Cannot read file."); entries.push(FIINEntry { file_size: file.len() as i32, file_name: name.to_string(), sha1: sha1_smol::Sha1::from(file).digest().bytes().to_vec() }); } Some(FileInfo { entries }) } }