swf_parser/streaming/parser/
mod.rs1use std::fmt;
2
3use crate::stream_buffer::{FlatBuffer, StreamBuffer};
4use crate::streaming::movie::parse_swf_signature;
5use swf_types::CompressionMethod;
6use swf_types::{Header as SwfHeader, Tag};
7
8mod simple;
9#[cfg(feature="deflate")]
10mod deflate;
11#[cfg(feature="lzma")]
12mod lzma;
13
14use simple::SimpleStream;
15#[cfg(feature="deflate")]
16use deflate::DeflateStream;
17#[cfg(feature="lzma")]
18use lzma::LzmaStream;
19
20pub struct HeaderParser(InnerHeaderParser);
28
29enum InnerHeaderParser {
31 Signature(Vec<u8>),
33 Simple(SimpleStream<FlatBuffer>),
35 #[cfg(feature="deflate")]
38 Deflate(DeflateStream<FlatBuffer>),
39 #[cfg(feature="lzma")]
42 Lzma(LzmaStream<FlatBuffer>),
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
46pub enum HeaderParserError {
47 MissingFeature(&'static str),
49 Other,
51}
52
53impl std::error::Error for HeaderParserError {}
54
55impl fmt::Display for HeaderParserError {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 match self {
58 HeaderParserError::MissingFeature(feat) => write!(
59 f,
60 "unsupported compression type in SWF header: compile `swf-parser` with the `{}` feature",
61 feat,
62 ),
63 HeaderParserError::Other => f.write_str("couldn't parse SWF header"),
64 }
65 }
66}
67
68impl HeaderParser {
69 pub fn new() -> Self {
71 Self(InnerHeaderParser::Signature(Vec::new()))
72 }
73
74 pub fn header(self, bytes: &[u8]) -> Result<(SwfHeader, TagParser), (Self, HeaderParserError)> {
85 match self.0 {
86 InnerHeaderParser::Signature(mut buffer) => {
87 let (input, parser) = Self::parser_from_signature(&mut buffer, bytes)?;
88 parser.header(input)
89 }
90 InnerHeaderParser::Simple(stream) => HeaderParser::simple_header(stream, bytes).map_err(|this| (this, HeaderParserError::Other)),
91 #[cfg(feature="lzma")]
92 InnerHeaderParser::Lzma(stream) => HeaderParser::lzma_header(stream, bytes).map_err(|this| (this, HeaderParserError::Other)),
93 #[cfg(feature="deflate")]
94 InnerHeaderParser::Deflate(stream) => HeaderParser::deflate_header(stream, bytes).map_err(|this| (this, HeaderParserError::Other)),
95 }
96 }
97
98 fn parser_from_signature<'a>(buffer: &'a mut Vec<u8>, bytes: &[u8]) -> Result<(&'a [u8], Self), (Self, HeaderParserError)> {
99 buffer.extend_from_slice(bytes);
100
101 let consumed_and_sig = parse_swf_signature(&*buffer).map(|(remaining, signature)| {
103 (buffer.len() - remaining.len(), signature)
104 });
105 let (input, signature) = match consumed_and_sig {
106 Ok((off, signature)) => (&buffer[off..], signature),
107 Err(_) => return Err((Self(InnerHeaderParser::Signature(std::mem::take(buffer))), HeaderParserError::Other)),
108 };
109
110 let buffer: FlatBuffer = FlatBuffer::new();
111 let parser = match signature.compression_method {
112 CompressionMethod::None => InnerHeaderParser::Simple(SimpleStream::new(buffer, signature)),
113 #[cfg(feature="lzma")]
114 CompressionMethod::Lzma => InnerHeaderParser::Lzma(LzmaStream::new(buffer, signature)),
115 #[cfg(not(feature="lzma"))]
116 CompressionMethod::Lzma => return Err((Self(InnerHeaderParser::Signature(std::mem::take(buffer))), HeaderParserError::MissingFeature("lzma"))),
117 #[cfg(feature="deflate")]
118 CompressionMethod::Deflate => InnerHeaderParser::Deflate(DeflateStream::new(buffer, signature)),
119 #[cfg(not(feature="deflate"))]
120 CompressionMethod::Deflate => return Err((Self(InnerHeaderParser::Signature(std::mem::take(buffer))), HeaderParserError::MissingFeature("deflate"))),
121 };
122 Ok((input, Self(parser)))
123 }
124
125 fn simple_header(mut stream: SimpleStream<FlatBuffer>, bytes: &[u8]) -> Result<(SwfHeader, TagParser), Self> {
127 stream.write(bytes);
128 match stream.header() {
129 Ok((header, stream)) => Ok((header, TagParser(InnerTagParser::Simple(stream)))),
130 Err(stream) => Err(Self(InnerHeaderParser::Simple(stream))),
131 }
132 }
133
134 #[cfg(feature="lzma")]
136 fn lzma_header(mut stream: LzmaStream<FlatBuffer>, bytes: &[u8]) -> Result<(SwfHeader, TagParser), Self> {
137 stream.write(bytes);
138 match stream.header() {
139 Ok((header, stream)) => Ok((header, TagParser(InnerTagParser::Lzma(stream)))),
140 Err(stream) => Err(Self(InnerHeaderParser::Lzma(stream))),
141 }
142 }
143
144 #[cfg(feature="deflate")]
146 fn deflate_header(mut stream: DeflateStream<FlatBuffer>, bytes: &[u8]) -> Result<(SwfHeader, TagParser), Self> {
147 stream.write(bytes);
148 match stream.header() {
149 Ok((header, stream)) => Ok((header, TagParser(InnerTagParser::Deflate(stream)))),
150 Err(stream) => Err(Self(InnerHeaderParser::Deflate(stream))),
151 }
152 }
153}
154
155impl Default for HeaderParser {
156 fn default() -> Self {
157 Self::new()
158 }
159}
160
161pub struct TagParser(InnerTagParser);
172
173enum InnerTagParser {
174 Simple(SimpleStream<FlatBuffer>),
176 #[cfg(feature="deflate")]
178 Deflate(DeflateStream<FlatBuffer>),
179 #[cfg(feature="lzma")]
181 Lzma(LzmaStream<FlatBuffer>),
182}
183
184#[derive(Debug)]
186pub struct ParseTagsError;
187
188impl std::error::Error for ParseTagsError {}
189
190impl fmt::Display for ParseTagsError {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 f.write_str("failed to parse SWF tag")
193 }
194}
195
196impl TagParser {
197 pub fn tags(&mut self, bytes: &[u8]) -> Result<Option<Vec<Tag>>, ParseTagsError> {
202 match &mut self.0 {
203 InnerTagParser::Simple(ref mut stream) => {
204 stream.write(bytes);
205 stream.tags()
206 }
207 #[cfg(feature="deflate")]
208 InnerTagParser::Deflate(ref mut stream) => {
209 stream.write(bytes);
210 stream.tags()
211 }
212 #[cfg(feature="lzma")]
213 InnerTagParser::Lzma(ref mut stream) => {
214 stream.write(bytes);
215 stream.tags()
216 }
217 }
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224 use swf_types::Movie;
225
226 #[test]
227 fn test_stream_parse_blank() {
228 let movie_ast_bytes: &[u8] = include_bytes!("../../../../tests/movies/blank/ast.json");
229 let expected: Movie = serde_json_v8::from_slice::<Movie>(movie_ast_bytes).expect("Failed to read AST");
230
231 let movie_bytes: &[u8] = include_bytes!("../../../../tests/movies/blank/main.swf");
232 let mut movie_bytes = movie_bytes.iter().copied().enumerate();
233
234 let mut parser = HeaderParser::new();
235 let mut header_output: Option<(SwfHeader, TagParser)> = None;
236 for (index, byte) in movie_bytes.by_ref() {
237 match parser.header(&[byte]) {
238 Ok((header, tag_parser)) => {
239 assert_eq!(index, 20);
240 header_output = Some((header, tag_parser));
241 break;
242 }
243 Err((next_parser, HeaderParserError::Other)) => parser = next_parser,
244 Err((_, e)) => panic!("{e:?}"),
245 }
246 }
247 assert!(header_output.is_some());
248 let (header, mut parser) = header_output.unwrap();
249 let mut tags: Vec<Tag> = Vec::new();
250 for (index, byte) in movie_bytes {
251 match parser.tags(&[byte]) {
252 Ok(Some(new_tags)) => tags.extend_from_slice(&new_tags),
253 Ok(None) => {
254 assert_eq!(index, 52);
255 break;
256 }
257 Err(_) => {}
258 }
259 }
260 let actual: Movie = Movie { header, tags };
261 assert_eq!(actual, expected);
262 }
263}