zipatch-rs 1.0.0

Parser for FFXIV ZiPatch patch files
Documentation
use binrw::BinRead;
use std::io::Cursor;

/// `APFS` chunk: free-space book-keeping; ignored at apply time.
#[derive(BinRead, Debug, Clone, PartialEq, Eq)]
#[br(big)]
pub struct ApplyFreeSpace {
    /// First 8-byte value (purpose undocumented in the wire format).
    #[br(map = |x: u64| x as i64)]
    pub unknown_a: i64,
    /// Second 8-byte value (purpose undocumented in the wire format).
    #[br(map = |x: u64| x as i64)]
    pub unknown_b: i64,
}

pub(crate) fn parse(body: &[u8]) -> crate::Result<ApplyFreeSpace> {
    Ok(ApplyFreeSpace::read_be(&mut Cursor::new(body))?)
}

#[cfg(test)]
mod tests {
    use super::parse;

    #[test]
    fn parses_apply_free_space() {
        let mut body = Vec::new();
        body.extend_from_slice(&0x8000000000000000u64.to_be_bytes()); // high bit → i64::MIN
        body.extend_from_slice(&1u64.to_be_bytes());
        let cmd = parse(&body).unwrap();
        assert_eq!(cmd.unknown_a, i64::MIN);
        assert_eq!(cmd.unknown_b, 1);
    }

    #[test]
    fn rejects_truncated_body() {
        // 16-byte body needed (two u64); supply only 8 to trigger the `?` error arm.
        assert!(parse(&[0u8; 8]).is_err());
    }
}