Skip to main content

flash_lso/packet/
read.rs

1use nom::branch::alt;
2use nom::bytes::complete::tag;
3use nom::number::complete::{be_u8, be_u16, be_u32};
4use std::convert::TryInto;
5
6use crate::amf0;
7use crate::amf0::read::AMF0Decoder;
8use crate::errors::Error;
9use crate::nom_utils::AMFResult;
10use crate::packet::{Header, Message, Packet};
11use crate::types::AMFVersion;
12use nom::Parser;
13use nom::combinator::all_consuming;
14use nom::multi::length_count;
15
16const FORMAT_VERSION_AMF0: u8 = 0x0;
17const FORMAT_VERSION_AMF3: u8 = 0x3;
18
19fn parse_header(i: &[u8]) -> AMFResult<'_, Header> {
20    let (i, name) = amf0::read::parse_string(i)?;
21    let (i, must_understand) = be_u8(i)?;
22    let (i, _length) = be_u32(i)?;
23    let (i, value) = AMF0Decoder::default().parse_single_element(i)?;
24
25    Ok((
26        i,
27        Header {
28            name: name.to_string(),
29            must_understand: must_understand != 0,
30            value: (value),
31        },
32    ))
33}
34
35fn parse_message(i: &[u8]) -> AMFResult<'_, Message> {
36    let (i, target_uri) = amf0::read::parse_string(i)?;
37    let (i, response_uri) = amf0::read::parse_string(i)?;
38    let (i, _length) = be_u32(i)?;
39    let (i, contents) = AMF0Decoder::default().parse_single_element(i)?;
40
41    Ok((
42        i,
43        Message {
44            target_uri: target_uri.to_string(),
45            response_uri: response_uri.to_string(),
46            contents: (contents),
47        },
48    ))
49}
50
51/// Read a given buffer as a packet
52///
53/// Unlike parse, this function will not error if the entire slice isn't consumed
54/// and will return the data that was not parsed
55pub fn parse_incomplete(i: &[u8]) -> AMFResult<'_, Packet> {
56    let (i, _) = tag([0u8].as_slice())(i)?;
57    let (i, version) = alt((
58        tag([FORMAT_VERSION_AMF0].as_slice()),
59        tag([FORMAT_VERSION_AMF3].as_slice()),
60    ))
61    .parse(i)?;
62    // This unwrap can't fail because of the alt above
63    let version: AMFVersion = version[0].try_into().expect("Invalid version");
64
65    let (i, headers) = length_count(be_u16, parse_header).parse(i)?;
66    let (i, messages) = length_count(be_u16, parse_message).parse(i)?;
67
68    Ok((
69        i,
70        Packet {
71            version,
72            headers,
73            messages,
74        },
75    ))
76}
77
78/// Read a given slice as a packet
79///
80/// This function will return an error if the slice could not be parsed or if the entire slice
81/// was not consumed
82pub fn parse(i: &[u8]) -> Result<Packet, nom::Err<Error<'_>>> {
83    let (_, packet) = all_consuming(|i| parse_incomplete(i)).parse(i)?;
84    Ok(packet)
85}