1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use nom::{IResult as NomResult, Needed};
use crate::parsers::header::{parse_header, parse_swf_signature};
use crate::parsers::tags::parse_swf_tag;
use crate::state::ParseState;
use swf_tree as ast;
pub fn parse_tag_block_string<'a>(input: &'a [u8], state: &mut ParseState) -> NomResult<&'a [u8], Vec<ast::Tag>> {
let mut result: Vec<ast::Tag> = Vec::new();
let mut current_input: &[u8] = input;
while current_input.len() > 0 {
if current_input[0] == 0 {
current_input = ¤t_input[1..];
break;
}
match parse_swf_tag(current_input, state) {
Ok((next_input, swf_tag)) => {
current_input = next_input;
result.push(swf_tag);
}
Err(::nom::Err::Incomplete(_)) => return Err(::nom::Err::Incomplete(Needed::Unknown)),
Err(e) => return Err(e),
};
}
Ok((current_input, result))
}
pub fn parse_movie_payload(input: &[u8], swf_version: u8) -> NomResult<&[u8], ast::Movie> {
let mut state = ParseState::new(swf_version);
do_parse!(
input,
header: call!(parse_header, swf_version) >>
tags: apply!(parse_tag_block_string, &mut state) >>
(ast::Movie {
header: header,
tags: tags,
})
)
}
pub fn parse_movie(input: &[u8]) -> NomResult<&[u8], ast::Movie> {
use ::std::io::Write;
let (input, signature) = parse_swf_signature(input)?;
match signature.compression_method {
ast::CompressionMethod::None => parse_movie_payload(input, signature.swf_version),
ast::CompressionMethod::Deflate => {
let mut decoder = ::inflate::InflateWriter::from_zlib(Vec::new());
decoder.write(input).unwrap();
let payload = decoder.finish().unwrap();
match parse_movie_payload(&payload[..], signature.swf_version) {
Ok((_, movie)) => Ok((&[][..], movie)),
Err(::nom::Err::Error(::nom::simple_errors::Context::Code(_, e))) => Err(::nom::Err::Error(::nom::simple_errors::Context::Code(&[][..], e))),
Err(::nom::Err::Failure(::nom::simple_errors::Context::Code(_, e))) => Err(::nom::Err::Failure(::nom::simple_errors::Context::Code(&[][..], e))),
Err(::nom::Err::Incomplete(n)) => Err(::nom::Err::Incomplete(n)),
}
}
ast::CompressionMethod::Lzma => {
unimplemented!()
}
}
}