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
51pub 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 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
78pub fn parse(i: &[u8]) -> Result<Packet, nom::Err<Error<'_>>> {
83 let (_, packet) = all_consuming(|i| parse_incomplete(i)).parse(i)?;
84 Ok(packet)
85}