zipatch_rs/chunk/sqpk/
add_data.rs1use binrw::BinRead;
2use std::io::Cursor;
3
4use super::SqpackFile;
5
6const SQPK_ADDDATA_HEADER_SIZE: u64 = 23;
9
10#[derive(BinRead, Debug, Clone, PartialEq, Eq)]
13#[br(big)]
14pub struct SqpkAddData {
15 #[br(pad_before = 3)]
17 pub target_file: SqpackFile,
18 #[br(map = |raw: u32| (raw as u64) << 7)]
20 pub block_offset: u64,
21 #[br(map = |raw: u32| (raw as u64) << 7)]
23 pub data_bytes: u64,
24 #[br(map = |raw: u32| (raw as u64) << 7)]
26 pub block_delete_number: u64,
27 #[br(count = data_bytes)]
29 pub data: Vec<u8>,
30}
31
32impl SqpkAddData {
33 pub const DATA_SOURCE_OFFSET: u64 = SQPK_ADDDATA_HEADER_SIZE;
38}
39
40pub(crate) fn parse(body: &[u8]) -> crate::Result<SqpkAddData> {
41 Ok(SqpkAddData::read_be(&mut Cursor::new(body))?)
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn parses_add_data() {
50 let mut body = Vec::new();
51 body.extend_from_slice(&[0u8; 3]); body.extend_from_slice(&1u16.to_be_bytes()); body.extend_from_slice(&2u16.to_be_bytes()); body.extend_from_slice(&3u32.to_be_bytes()); body.extend_from_slice(&1u32.to_be_bytes()); body.extend_from_slice(&1u32.to_be_bytes()); body.extend_from_slice(&0u32.to_be_bytes()); body.extend_from_slice(&[0xABu8; 128]); let cmd = parse(&body).unwrap();
61 assert_eq!(cmd.target_file.main_id, 1);
62 assert_eq!(cmd.target_file.sub_id, 2);
63 assert_eq!(cmd.target_file.file_id, 3);
64 assert_eq!(cmd.block_offset, 128);
65 assert_eq!(cmd.data_bytes, 128);
66 assert_eq!(cmd.block_delete_number, 0);
67 assert_eq!(cmd.data.len(), 128);
68 assert!(cmd.data.iter().all(|&b| b == 0xAB));
69 assert_eq!(SqpkAddData::DATA_SOURCE_OFFSET, 23);
70 }
71}