Mercurial > touhou
comparison src/th06/anm0.rs @ 694:3ff1af76e413
anm0: only use recoverable errors, no panics except for anm0 asserts.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Fri, 23 Aug 2019 02:24:08 +0200 |
parents | 7bde50132735 |
children | b6c351ca0a35 |
comparison
equal
deleted
inserted
replaced
693:14fddc27e6f5 | 694:3ff1af76e413 |
---|---|
87 fn parse_name(i: &[u8], is_present: bool) -> IResult<&[u8], String> { | 87 fn parse_name(i: &[u8], is_present: bool) -> IResult<&[u8], String> { |
88 if !is_present { | 88 if !is_present { |
89 return Ok((i, String::new())); | 89 return Ok((i, String::new())); |
90 } | 90 } |
91 let (_, slice) = take_while_m_n(0, 32, |c| c != 0)(i)?; | 91 let (_, slice) = take_while_m_n(0, 32, |c| c != 0)(i)?; |
92 // XXX: no unwrap! | 92 let string = match String::from_utf8(slice.to_vec()) { |
93 let string = String::from_utf8(slice.to_vec()).unwrap(); | 93 Ok(string) => string, |
94 // XXX: use a more specific error instead. | |
95 Err(_) => return Err(nom::Err::Failure((i, nom::error::ErrorKind::Eof))) | |
96 }; | |
94 Ok((i, string)) | 97 Ok((i, string)) |
95 } | 98 } |
96 | 99 |
97 fn parse_sprite(i: &[u8]) -> IResult<&[u8], Sprite> { | 100 fn parse_sprite(i: &[u8]) -> IResult<&[u8], Sprite> { |
98 let (i, index) = le_u32(i)?; | 101 let (i, index) = le_u32(i)?; |
118 $( | 121 $( |
119 $name($($arg_type),*) | 122 $name($($arg_type),*) |
120 ),* | 123 ),* |
121 } | 124 } |
122 | 125 |
123 fn parse_instruction_args(input: &[u8], opcode: u8) -> IResult<&[u8], Instruction> { | 126 fn parse_instruction_args(mut i: &[u8], opcode: u8) -> IResult<&[u8], Instruction> { |
124 let mut i = &input[..]; | |
125 let instr = match opcode { | 127 let instr = match opcode { |
126 $( | 128 $( |
127 $opcode => { | 129 $opcode => { |
128 $( | 130 $( |
129 let (i2, $arg) = concat_idents!(le_, $arg_type)(i)?; | 131 let (i2, $arg) = concat_idents!(le_, $arg_type)(i)?; |
130 i = i2; | 132 i = i2; |
131 )* | 133 )* |
132 Instruction::$name($($arg),*) | 134 Instruction::$name($($arg),*) |
133 } | 135 } |
134 )* | 136 )* |
135 _ => unreachable!() | 137 // XXX: use a more specific error instead. |
138 _ => return Err(nom::Err::Failure((i, nom::error::ErrorKind::Eof))) | |
136 }; | 139 }; |
137 Ok((i, instr)) | 140 Ok((i, instr)) |
138 } | 141 } |
139 }; | 142 }; |
140 } | 143 } |
211 let (i2, offset) = le_u32(i2)?; | 214 let (i2, offset) = le_u32(i2)?; |
212 script_offsets.push((index as u8, offset as usize)); | 215 script_offsets.push((index as u8, offset as usize)); |
213 i = i2; | 216 i = i2; |
214 } | 217 } |
215 | 218 |
219 if input.len() < start_offset + first_name_offset as usize { | |
220 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); | |
221 } | |
216 let i = &input[start_offset + first_name_offset as usize..]; | 222 let i = &input[start_offset + first_name_offset as usize..]; |
217 let (_, first_name) = parse_name(i, first_name_offset > 0)?; | 223 let (_, first_name) = parse_name(i, first_name_offset > 0)?; |
218 | 224 |
225 if input.len() < start_offset + second_name_offset as usize { | |
226 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); | |
227 } | |
219 let i = &input[start_offset + second_name_offset as usize..]; | 228 let i = &input[start_offset + second_name_offset as usize..]; |
220 let (_, second_name) = parse_name(i, second_name_offset > 0)?; | 229 let (_, second_name) = parse_name(i, second_name_offset > 0)?; |
221 | 230 |
222 let mut sprites = vec![]; | 231 let mut sprites = vec![]; |
223 let mut i; | 232 let mut i; |
224 for offset in sprite_offsets { | 233 for offset in sprite_offsets { |
234 if input.len() < start_offset + offset { | |
235 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); | |
236 } | |
225 i = &input[start_offset + offset..]; | 237 i = &input[start_offset + offset..]; |
226 let (_, sprite) = parse_sprite(i)?; | 238 let (_, sprite) = parse_sprite(i)?; |
227 sprites.push(sprite); | 239 sprites.push(sprite); |
228 } | 240 } |
229 | 241 |
230 let mut scripts = HashMap::new(); | 242 let mut scripts = HashMap::new(); |
231 for (index, offset) in script_offsets { | 243 for (index, offset) in script_offsets { |
244 if input.len() < start_offset + offset { | |
245 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); | |
246 } | |
232 i = &input[start_offset + offset..]; | 247 i = &input[start_offset + offset..]; |
233 let mut instruction_offsets = vec![]; | 248 let mut instruction_offsets = vec![]; |
234 | 249 |
235 let mut instructions = vec![]; | 250 let mut instructions = vec![]; |
236 loop { | 251 loop { |
253 match instr { | 268 match instr { |
254 Instruction::Jump(ref mut offset) => { | 269 Instruction::Jump(ref mut offset) => { |
255 let result = instruction_offsets.binary_search(&(*offset as usize)); | 270 let result = instruction_offsets.binary_search(&(*offset as usize)); |
256 match result { | 271 match result { |
257 Ok(ptr) => *offset = ptr as u32, | 272 Ok(ptr) => *offset = ptr as u32, |
258 // TODO: make that a recoverable error instead. | 273 Err(ptr) => { |
259 Err(ptr) => panic!("Instruction offset not found for pointer: {}", ptr), | 274 // XXX: use a more specific error instead. |
275 return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); | |
276 //println!("Instruction offset not found for pointer: {}", ptr); | |
277 } | |
260 } | 278 } |
261 } | 279 } |
262 Instruction::InterruptLabel(interrupt) => { | 280 Instruction::InterruptLabel(interrupt) => { |
263 interrupts.insert(*interrupt, j + 1); | 281 interrupts.insert(*interrupt, j + 1); |
264 } | 282 } |