comparison src/th06/anm0.rs @ 702:718348c7608e

anm0: simplify parsing with more combinators.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 23 Aug 2019 17:22:38 +0200
parents b6c351ca0a35
children 84af5bedbde4
comparison
equal deleted inserted replaced
701:b6c351ca0a35 702:718348c7608e
2 2
3 use nom::{ 3 use nom::{
4 IResult, 4 IResult,
5 bytes::complete::{tag, take_while_m_n}, 5 bytes::complete::{tag, take_while_m_n},
6 number::complete::{le_u8, le_u16, le_u32, le_i32, le_f32}, 6 number::complete::{le_u8, le_u16, le_u32, le_i32, le_f32},
7 sequence::tuple,
8 multi::many_m_n,
7 }; 9 };
8 use std::collections::HashMap; 10 use std::collections::HashMap;
9 11
10 /// Coordinates of a sprite into the image. 12 /// Coordinates of a sprite into the image.
11 #[derive(Debug, Clone)] 13 #[derive(Debug, Clone)]
79 let (x, y) = self.size; 81 let (x, y) = self.size;
80 (1. / x as f32, 1. / y as f32) 82 (1. / x as f32, 1. / y as f32)
81 } 83 }
82 } 84 }
83 85
84 fn parse_name(i: &[u8], is_present: bool) -> IResult<&[u8], String> { 86 fn parse_name(i: &[u8]) -> IResult<&[u8], String> {
85 if !is_present {
86 return Ok((i, String::new()));
87 }
88 let (_, slice) = take_while_m_n(0, 32, |c| c != 0)(i)?; 87 let (_, slice) = take_while_m_n(0, 32, |c| c != 0)(i)?;
89 let string = match String::from_utf8(slice.to_vec()) { 88 let string = match String::from_utf8(slice.to_vec()) {
90 Ok(string) => string, 89 Ok(string) => string,
91 // XXX: use a more specific error instead. 90 // XXX: use a more specific error instead.
92 Err(_) => return Err(nom::Err::Failure((i, nom::error::ErrorKind::Eof))) 91 Err(_) => return Err(nom::Err::Failure((i, nom::error::ErrorKind::Eof)))
93 }; 92 };
94 Ok((i, string)) 93 Ok((i, string))
95 } 94 }
96 95
97 fn parse_sprite(i: &[u8]) -> IResult<&[u8], Sprite> { 96 fn parse_sprite(i: &[u8]) -> IResult<&[u8], Sprite> {
98 let (i, index) = le_u32(i)?; 97 let (i, (index, x, y, width, height)) = tuple((le_u32, le_f32, le_f32, le_f32, le_f32))(i)?;
99 let (i, x) = le_f32(i)?;
100 let (i, y) = le_f32(i)?;
101 let (i, width) = le_f32(i)?;
102 let (i, height) = le_f32(i)?;
103 Ok((i, Sprite { 98 Ok((i, Sprite {
104 index, 99 index,
105 x, 100 x,
106 y, 101 y,
107 width, 102 width,
175 fn parse_anm0(input: &[u8]) -> IResult<&[u8], Vec<Anm0>> { 170 fn parse_anm0(input: &[u8]) -> IResult<&[u8], Vec<Anm0>> {
176 let mut list = vec![]; 171 let mut list = vec![];
177 let start_offset = 0; 172 let start_offset = 0;
178 loop { 173 loop {
179 let i = &input[start_offset..]; 174 let i = &input[start_offset..];
180 let (i, num_sprites) = le_u32(i)?; 175 let (mut i, (num_sprites, num_scripts, _, width, height, format, _unknown1,
181 let (i, num_scripts) = le_u32(i)?; 176 first_name_offset, _unused, second_name_offset, version, _unknown2,
182 let (i, _) = tag(b"\0\0\0\0")(i)?; 177 _texture_offset, has_data, _next_offset, unknown3)) =
183 let (i, width) = le_u32(i)?; 178 tuple((le_u32, le_u32, tag(b"\0\0\0\0"), le_u32, le_u32, le_u32, le_u32, le_u32,
184 let (i, height) = le_u32(i)?; 179 le_u32, le_u32, le_u32, le_u32, le_u32, le_u32, le_u32, le_u32))(i)?;
185 let (i, format) = le_u32(i)?;
186 let (i, _unknown1) = le_u32(i)?;
187 let (i, first_name_offset) = le_u32(i)?;
188 let (i, _unused) = le_u32(i)?;
189 let (i, second_name_offset) = le_u32(i)?;
190 let (i, version) = le_u32(i)?;
191 let (i, _unknown2) = le_u32(i)?;
192 let (i, _texture_offset) = le_u32(i)?;
193 let (i, has_data) = le_u32(i)?;
194 let (i, _next_offset) = le_u32(i)?;
195 let (mut i, unknown3) = le_u32(i)?;
196 180
197 assert_eq!(version, 0); 181 assert_eq!(version, 0);
198 assert_eq!(unknown3, 0); 182 assert_eq!(unknown3, 0);
199 assert_eq!(has_data, 0); 183 assert_eq!(has_data, 0);
200 184 let num_sprites = num_sprites as usize;
201 let mut sprite_offsets = vec![]; 185 let num_scripts = num_scripts as usize;
202 for _ in 0..num_sprites { 186
203 let (i2, offset) = le_u32(i)?; 187 let (i, sprite_offsets) = many_m_n(num_sprites, num_sprites, le_u32)(i)?;
204 sprite_offsets.push(offset as usize); 188 let (_, script_offsets) = many_m_n(num_scripts, num_scripts, tuple((le_u32, le_u32)))(i)?;
205 i = i2; 189
206 } 190 let first_name = if first_name_offset > 0 {
207 191 if input.len() < start_offset + first_name_offset as usize {
208 let mut script_offsets = vec![]; 192 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof)));
209 for _ in 0..num_scripts { 193 }
210 let (i2, index) = le_u32(i)?; 194 let i = &input[start_offset + first_name_offset as usize..];
211 let (i2, offset) = le_u32(i2)?; 195 let (_, name) = parse_name(i)?;
212 script_offsets.push((index as u8, offset as usize)); 196 name
213 i = i2; 197 } else {
214 } 198 String::new()
215 199 };
216 if input.len() < start_offset + first_name_offset as usize { 200
217 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); 201 let second_name = if second_name_offset > 0 {
218 } 202 if input.len() < start_offset + second_name_offset as usize {
219 let i = &input[start_offset + first_name_offset as usize..]; 203 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof)));
220 let (_, first_name) = parse_name(i, first_name_offset > 0)?; 204 }
221 205 let i = &input[start_offset + second_name_offset as usize..];
222 if input.len() < start_offset + second_name_offset as usize { 206 let (_, name) = parse_name(i)?;
223 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); 207 name
224 } 208 } else {
225 let i = &input[start_offset + second_name_offset as usize..]; 209 String::new()
226 let (_, second_name) = parse_name(i, second_name_offset > 0)?; 210 };
227 211
228 let mut sprites = vec![]; 212 let mut sprites = vec![];
229 let mut i; 213 let mut i;
230 for offset in sprite_offsets { 214 for offset in sprite_offsets.into_iter().map(|x| x as usize) {
231 if input.len() < start_offset + offset { 215 if input.len() < start_offset + offset {
232 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); 216 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof)));
233 } 217 }
234 i = &input[start_offset + offset..]; 218 i = &input[start_offset + offset..];
235 let (_, sprite) = parse_sprite(i)?; 219 let (_, sprite) = parse_sprite(i)?;
236 sprites.push(sprite); 220 sprites.push(sprite);
237 } 221 }
238 222
239 let mut scripts = HashMap::new(); 223 let mut scripts = HashMap::new();
240 for (index, offset) in script_offsets { 224 for (index, offset) in script_offsets.into_iter().map(|(index, offset)| (index as u8, offset as usize)) {
241 if input.len() < start_offset + offset { 225 if input.len() < start_offset + offset {
242 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); 226 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof)));
243 } 227 }
244 i = &input[start_offset + offset..]; 228 i = &input[start_offset + offset..];
245 let mut instruction_offsets = vec![]; 229 let mut instruction_offsets = vec![];
246 230
247 let mut instructions = vec![]; 231 let mut instructions = vec![];
248 loop { 232 loop {
249 let tell = input.len() - i.len(); 233 let tell = input.len() - i.len();
250 instruction_offsets.push(tell - (start_offset + offset)); 234 instruction_offsets.push(tell - (start_offset + offset));
251 let (i2, time) = le_u16(i)?;
252 let (i2, opcode) = le_u8(i2)?;
253 // TODO: maybe check against the size of parsed data? 235 // TODO: maybe check against the size of parsed data?
254 let (i2, _size) = le_u8(i2)?; 236 let (i2, (time, opcode, _size)) = tuple((le_u16, le_u8, le_u8))(i)?;
255 let (i2, instr) = parse_instruction_args(i2, opcode)?; 237 let (i2, instr) = parse_instruction_args(i2, opcode)?;
256 instructions.push(Call { time, instr }); 238 instructions.push(Call { time, instr });
257 i = i2; 239 i = i2;
258 if opcode == 0 { 240 if opcode == 0 {
259 break; 241 break;
285 instructions, 267 instructions,
286 interrupts, 268 interrupts,
287 }); 269 });
288 } 270 }
289 271
290 assert!(has_data == 0);
291
292 let anm0 = Anm0 { 272 let anm0 = Anm0 {
293 size: (width, height), 273 size: (width, height),
294 format, 274 format,
295 first_name, 275 first_name,
296 second_name, 276 second_name,