nom_mpq/parser/
mpq_user_data.rs1use super::LITTLE_ENDIAN;
9use crate::dbg_dmp;
10use nom::bytes::complete::take;
11use nom::number::complete::u32;
12use nom::*;
13
14#[derive(Debug, Default)]
16pub struct MPQUserData {
17 pub user_data_size: u32, pub archive_header_offset: u32,
21 pub user_data_header_size: u32,
23 pub content: Vec<u8>,
26}
27
28impl MPQUserData {
29 pub fn parse(input: &[u8]) -> IResult<&[u8], Self> {
31 let (input, user_data_size) = Self::parse_user_data_size(input)?;
32 let (input, archive_header_offset) = Self::parse_archive_header_offset(input)?;
33 let (input, user_data_header_size) = Self::parse_user_data_header_size(input)?;
34 let (input, content) = Self::parse_content(input, user_data_header_size)?;
35 let (input, _) =
36 Self::consume_until_header_offset(input, user_data_header_size, archive_header_offset)?;
37 Ok((
38 input,
39 MPQUserData {
40 user_data_size,
41 archive_header_offset,
42 user_data_header_size,
43 content,
44 },
45 ))
46 }
47
48 pub fn parse_user_data_size(input: &[u8]) -> IResult<&[u8], u32> {
54 dbg_dmp(u32(LITTLE_ENDIAN), "user_data_size")(input)
55 }
56
57 pub fn parse_archive_header_offset(input: &[u8]) -> IResult<&[u8], u32> {
62 dbg_dmp(u32(LITTLE_ENDIAN), "archive_header_offset")(input)
63 }
64
65 pub fn parse_user_data_header_size(input: &[u8]) -> IResult<&[u8], u32> {
68 dbg_dmp(u32(LITTLE_ENDIAN), "user_data_size")(input)
69 }
70
71 pub fn parse_content(input: &[u8], user_data_header_size: u32) -> IResult<&[u8], Vec<u8>> {
75 let (input, content) = dbg_dmp(take(user_data_header_size as usize), "content")(input)?;
76 Ok((input, content.to_vec()))
77 }
78
79 pub fn consume_until_header_offset(
83 input: &[u8],
84 user_data_header_size: u32,
85 archive_header_offset: u32,
86 ) -> IResult<&[u8], ()> {
87 let curr_read_byte_count = 16;
94 if archive_header_offset < user_data_header_size + curr_read_byte_count {
95 tracing::error!(
96 "Invalid archive_header_offset: {}, should be bigger than {}",
97 archive_header_offset,
98 user_data_header_size + curr_read_byte_count
99 );
100 return Err(nom::Err::Incomplete(nom::Needed::new(
101 (user_data_header_size + curr_read_byte_count) as usize,
102 )));
103 }
104 let (input, _) = dbg_dmp(
105 take((archive_header_offset - (user_data_header_size + curr_read_byte_count)) as usize),
106 "content",
107 )(input)?;
108 Ok((input, ()))
109 }
110}
111
112#[cfg(test)]
113pub mod tests {
115 use super::*;
116 use crate::parser::*;
117
118 pub fn basic_user_header() -> Vec<u8> {
120 vec![
122 b'M',
123 b'P',
124 b'Q', MPQ_USER_DATA_HEADER_TYPE,
126 0x00,
127 0x00,
128 0x00,
129 0x00, 0x18,
131 0x00,
132 0x00,
133 0x00, 0x04,
135 0x00,
136 0x00,
137 0x00, 0xbe,
139 0xef,
140 0xca,
141 0x4e, 0x00,
143 0x00,
144 0x00,
145 0x00, ]
147 }
148
149 #[test]
150 fn it_parses_header() {
151 let user_data_header_input = basic_user_header();
153 let (input, header_type) = get_header_type(&user_data_header_input).unwrap();
154 assert_eq!(header_type, MPQSectionType::UserData);
155 let (input, user_data) = MPQUserData::parse(input).unwrap();
156 assert_eq!(user_data.archive_header_offset, 0x18);
157 assert_eq!(user_data.user_data_header_size, 0x04);
158 assert_eq!(user_data.content, vec![0xbe, 0xef, 0xca, 0x4e]);
159 assert_eq!(input, &b""[..]);
160 }
161}