implement assemble_file function which assembles, or to be more accurate - patches file on the fly

This commit is contained in:
mykola2312 2023-08-26 16:08:33 +03:00
parent 5aa3b9738c
commit 8787394a26
3 changed files with 70 additions and 2 deletions

View file

@ -1 +1,2 @@
mod raw;
pub mod save;

50
src/fot/raw.rs Normal file
View file

@ -0,0 +1,50 @@
use std::io::Write;
use std::str;
use std::fs;
use std::fs::OpenOptions;
use std::path::Path;
use anyhow::Result;
// I can use traits to dynamically implement encode/decode for every header
// or I can just pass Vec<Block> with already encoded data to patch file
pub struct Raw {
pub offset: usize,
pub size: usize,
pub mem: Vec<u8>
}
impl Raw {
pub fn load_file(path: &Path) -> Result<Raw> {
let mem = fs::read(path)?;
Ok(Self { offset: 0, size: mem.len(), mem })
}
pub fn assemble_file(&self, path: &Path, blocks: Vec<Raw>) -> Result<()> {
let mut file = OpenOptions::new()
.create(true).truncate(true).write(true).open(path)?;
let mut sorted = blocks;
sorted.sort_by(|a, b| a.offset.cmp(&b.offset));
let file_end = self.size;
let mut prev_end: usize = 0;
for block in sorted.iter() {
// prev
file.write(&self.mem[prev_end..block.offset])?;
// data
file.write(&block.mem)?;
// padding
if block.size > block.mem.len() {
file.write(&vec![0; block.size - block.mem.len()])?;
}
prev_end = block.offset + block.size;
}
if prev_end < file_end {
file.write(&self.mem[prev_end..file_end])?;
}
Ok(())
}
}

View file

@ -7,6 +7,7 @@ use anyhow::anyhow;
use anyhow::Result;
use inflate::inflate_bytes_zlib;
use deflate::deflate_bytes_zlib;
use crate::fot::raw::Raw;
#[derive(Debug)]
pub struct World {
@ -93,7 +94,8 @@ impl Save {
file.write(&world.encode())?;
}*/
const START: usize = 0x99A84;
// determine world block size be next campaign
/*const START: usize = 0x99A84;
const END: usize = 0xD1B1E; //0xD1B1E;
const SIZE: usize = 0x38088;
//let world = self.worlds.last().unwrap();
@ -111,7 +113,22 @@ impl Save {
}
}
file.write(&self.raw[END+1..])?;
file.write(&self.raw[END+1..])?;*/
let raw = Raw { offset: 0, size: self.raw.len(), mem: self.raw.clone() };
const START: usize = 0x99A84;
const END: usize = 0xD1B1E; //0xD1B1E;
const SIZE: usize = 0x38088;
//let world = self.worlds.last().unwrap();
let world = World::decode(&self.raw, START, END - START)?;
let enc = world.encode();
let mut blocks: Vec<Raw> = Vec::new();
blocks.push(Raw {offset: START, size: 0x13, mem: self.raw[START..START+0x13].to_vec()});
blocks.push(Raw {offset: START+0x13, size: SIZE, mem: enc});
raw.assemble_file(path, blocks)?;
Ok(())
}