Eyepiece/src/lib.rs
2024-07-07 03:04:41 -05:00

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)?))
}
}