flash_lso/
read.rs

1use std::convert::TryInto;
2
3use nom::branch::alt;
4use nom::bytes::complete::tag;
5use nom::number::complete::be_u32;
6
7use crate::amf0;
8use crate::amf3::read::AMF3Decoder;
9use crate::nom_utils::AMFResult;
10use crate::types::{AMFVersion, Header, Lso};
11use nom::combinator::all_consuming;
12
13const HEADER_VERSION: [u8; 2] = [0x00, 0xbf];
14const HEADER_SIGNATURE: [u8; 10] = [0x54, 0x43, 0x53, 0x4f, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00];
15const PADDING: [u8; 1] = [0x00];
16
17const FORMAT_VERSION_AMF0: u8 = 0x0;
18const FORMAT_VERSION_AMF3: u8 = 0x3;
19
20/// The main entry point of decoding a LSO file
21/// Example of use
22/// ```
23/// use std::fs::File;
24/// use std::io::Read;
25/// use flash_lso::read::Reader;
26/// let mut x = File::open("tests/sol/AS2-Demo.sol").expect("Couldn't open file");
27/// let mut data = Vec::new();
28/// let _ = x.read_to_end(&mut data).expect("Unable to read file");
29/// let d = Reader::default().parse(&data).expect("Failed to parse lso file");
30/// println!("{:#?}", d);
31/// ```
32/// }
33#[derive(Default)]
34pub struct Reader {
35    /// Handles reading Value::AMF3() wrapped types
36    pub amf3_decoder: AMF3Decoder,
37}
38
39impl Reader {
40    fn parse_header<'a>(&self, i: &'a [u8]) -> AMFResult<'a, Header> {
41        let (i, _) = tag(HEADER_VERSION)(i)?;
42        let (i, l) = be_u32(i)?;
43        let (i, _) = tag(HEADER_SIGNATURE)(i)?;
44
45        let (i, name) = amf0::read::parse_string(i)?;
46
47        let (i, _) = tag(PADDING)(i)?;
48        let (i, _) = tag(PADDING)(i)?;
49        let (i, _) = tag(PADDING)(i)?;
50
51        let (i, version) = alt((tag(&[FORMAT_VERSION_AMF0]), tag(&[FORMAT_VERSION_AMF3])))(i)?;
52
53        // This unwrap can't fail because of the alt above
54        let format_version: AMFVersion = version[0].try_into().unwrap();
55
56        Ok((
57            i,
58            Header {
59                length: l,
60                name: name.to_string(),
61                format_version,
62            },
63        ))
64    }
65
66    fn parse_inner<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Lso> {
67        let (i, header) = self.parse_header(i)?;
68        match header.format_version {
69            AMFVersion::AMF0 => {
70                let (i, body) = amf0::read::parse_body(i)?;
71                Ok((i, Lso { header, body }))
72            }
73
74            AMFVersion::AMF3 => {
75                let (i, body) = self.amf3_decoder.parse_body(i)?;
76                Ok((i, Lso { header, body }))
77            }
78        }
79    }
80
81    /// Read a given buffer as an Lso
82    pub fn parse<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Lso> {
83        all_consuming(|i| self.parse_inner(i))(i)
84    }
85}