use std::env; use std::{ fs::{self, File}, io::{BufReader, Read}, }; use byteorder::{ByteOrder, LittleEndian}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] pub struct ImportListElement { pub extension: String, pub index: u32, pub name: String, pub unknown0: u32, pub unknown1: u32, pub unknown2: u32, } #[derive(Debug)] pub struct ListElement { pub extension: String, pub index: u32, pub name: String, pub position: u32, pub size: u32, pub unknown0: u32, pub unknown1: u32, pub unknown2: u32, } fn main() { let args: Vec = env::args().collect(); let input = &args[1]; let output = &args[2]; pack(String::from(input), String::from(output)); } fn pack(input: String, output: String) { // Загружаем индекс-файл let index_file = format!("{}/{}", input, "index.json"); let data = fs::read_to_string(index_file).unwrap(); let list: Vec = serde_json::from_str(&data).unwrap(); // Общий буфер хранения файлов let mut content_buffer: Vec = Vec::new(); let mut list_buffer: Vec = Vec::new(); // Общее количество файлов let total_files: u32 = list.len() as u32; for (index, item) in list.iter().enumerate() { // Открываем дескриптор файла let path = format!("{}/{}", input, item.name); let file = File::open(path).unwrap(); let metadata = file.metadata().unwrap(); // Считываем файл в буфер let mut reader = BufReader::new(file); let mut file_buffer: Vec = Vec::new(); reader.read_to_end(&mut file_buffer).unwrap(); // Выравнивание буфера if index != 0 { while content_buffer.len() % 8 != 0 { content_buffer.push(0); } } // Получение позиции файла let position = content_buffer.len() + 16; // Записываем файл в буфер content_buffer.extend(file_buffer); // Формируем элемент let element = ListElement { extension: item.extension.to_string(), index: item.index, name: item.name.to_string(), position: position as u32, size: metadata.len() as u32, unknown0: item.unknown0, unknown1: item.unknown1, unknown2: item.unknown2, }; // Создаем буфер из элемента let mut element_buffer: Vec = Vec::new(); // Пишем тип файла let mut extension_buffer: [u8; 4] = [0; 4]; let mut file_extension_buffer = element.extension.into_bytes(); file_extension_buffer.resize(4, 0); extension_buffer.copy_from_slice(&file_extension_buffer); element_buffer.extend(extension_buffer); // Пишем неизвестное значение #1 let mut unknown0_buffer: [u8; 4] = [0; 4]; LittleEndian::write_u32(&mut unknown0_buffer, element.unknown0); element_buffer.extend(unknown0_buffer); // Пишем неизвестное значение #2 let mut unknown1_buffer: [u8; 4] = [0; 4]; LittleEndian::write_u32(&mut unknown1_buffer, element.unknown1); element_buffer.extend(unknown1_buffer); // Пишем размер файла let mut file_size_buffer: [u8; 4] = [0; 4]; LittleEndian::write_u32(&mut file_size_buffer, element.size); element_buffer.extend(file_size_buffer); // Пишем неизвестное значение #3 let mut unknown2_buffer: [u8; 4] = [0; 4]; LittleEndian::write_u32(&mut unknown2_buffer, element.unknown2); element_buffer.extend(unknown2_buffer); // Пишем название файла let mut name_buffer: [u8; 36] = [0; 36]; let mut file_name_buffer = element.name.into_bytes(); file_name_buffer.resize(36, 0); name_buffer.copy_from_slice(&file_name_buffer); element_buffer.extend(name_buffer); // Пишем позицию файла let mut position_buffer: [u8; 4] = [0; 4]; LittleEndian::write_u32(&mut position_buffer, element.position); element_buffer.extend(position_buffer); // Пишем индекс файла let mut index_buffer: [u8; 4] = [0; 4]; LittleEndian::write_u32(&mut index_buffer, element.index); element_buffer.extend(index_buffer); // Добавляем итоговый буфер в буфер элементов списка list_buffer.extend(element_buffer); } let mut header_buffer: Vec = Vec::new(); // Пишем первый тип файла let mut header_type_1 = [0; 4]; LittleEndian::write_u32(&mut header_type_1, 1936020046_u32); header_buffer.extend(header_type_1); // Пишем второй тип файла let mut header_type_2 = [0; 4]; LittleEndian::write_u32(&mut header_type_2, 256_u32); header_buffer.extend(header_type_2); // Пишем количество файлов let mut header_total_files = [0; 4]; LittleEndian::write_u32(&mut header_total_files, total_files); header_buffer.extend(header_total_files); // Пишем общий размер файла let mut header_total_size = [0; 4]; let total_size: u32 = ((content_buffer.len() + 16) as u32) + (total_files * 64); LittleEndian::write_u32(&mut header_total_size, total_size); header_buffer.extend(header_total_size); let mut result_buffer: Vec = Vec::new(); result_buffer.extend(header_buffer); result_buffer.extend(content_buffer); result_buffer.extend(list_buffer); fs::write(output, result_buffer).unwrap(); }