54 lines
1.5 KiB
Rust
54 lines
1.5 KiB
Rust
//! Simple IPS file parsing and application
|
|
|
|
pub use ips::IPS;
|
|
use std::io::{Result as IoResult, Seek, Write};
|
|
|
|
pub mod ips;
|
|
|
|
/// Patches a [seekable](Seek) [writer](Write) with the provided [patch](Apply)
|
|
pub trait Patchable: Write + Seek {
|
|
fn patch<P: Apply>(&mut self, with: P) -> IoResult<&mut Self>;
|
|
}
|
|
|
|
impl<W: Write + Seek> Patchable for W {
|
|
/// Applies the provided patch to this [seekable](Seek) [writer](Write)
|
|
fn patch<P: Apply>(&mut self, with: P) -> IoResult<&mut Self> {
|
|
with.apply(self)?;
|
|
Ok(self)
|
|
}
|
|
}
|
|
|
|
/// Applies a patch to a [seekable](Seek) [writer](Write)
|
|
pub trait Apply {
|
|
/// Applies this patch to the provided [seekable](Seek) [writer](Write)
|
|
fn apply<W: Write + Seek>(&self, writer: &mut W) -> IoResult<()>;
|
|
}
|
|
|
|
mod parse_utils {
|
|
use std::io;
|
|
|
|
pub fn read_bytes<const N: usize>(reader: &mut impl io::Read) -> io::Result<[u8; N]> {
|
|
let mut buf = [0; N];
|
|
reader.read_exact(&mut buf).map(|_| buf)
|
|
}
|
|
|
|
/// Parses a 24-bit big-endian "offset" and ensures it isn't `0x454f46` (`b"EOF"`)
|
|
pub fn offset(reader: &mut impl io::Read) -> io::Result<Option<u32>> {
|
|
let buf = read_bytes(reader)?;
|
|
|
|
if buf == *b"EOF" {
|
|
return Ok(None);
|
|
}
|
|
|
|
let mut offset = 0;
|
|
for byte in buf {
|
|
offset = offset << 8 | byte as u32;
|
|
}
|
|
Ok(Some(offset))
|
|
}
|
|
|
|
pub fn read16(reader: &mut impl io::Read) -> io::Result<u16> {
|
|
Ok(u16::from_be_bytes(read_bytes(reader)?))
|
|
}
|
|
}
|