use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::number::complete::{be_u8, be_u16, be_u32};
use std::convert::TryInto;
use crate::amf0;
use crate::amf0::read::AMF0Decoder;
use crate::errors::Error;
use crate::nom_utils::AMFResult;
use crate::packet::{Header, Message, Packet};
use crate::types::AMFVersion;
use nom::Parser;
use nom::combinator::all_consuming;
use nom::multi::length_count;
const FORMAT_VERSION_AMF0: u8 = 0x0;
const FORMAT_VERSION_AMF3: u8 = 0x3;
fn parse_header(i: &[u8]) -> AMFResult<'_, Header> {
let (i, name) = amf0::read::parse_string(i)?;
let (i, must_understand) = be_u8(i)?;
let (i, _length) = be_u32(i)?;
let (i, value) = AMF0Decoder::default().parse_single_element(i)?;
Ok((
i,
Header {
name: name.to_string(),
must_understand: must_understand != 0,
value: (value),
},
))
}
fn parse_message(i: &[u8]) -> AMFResult<'_, Message> {
let (i, target_uri) = amf0::read::parse_string(i)?;
let (i, response_uri) = amf0::read::parse_string(i)?;
let (i, _length) = be_u32(i)?;
let (i, contents) = AMF0Decoder::default().parse_single_element(i)?;
Ok((
i,
Message {
target_uri: target_uri.to_string(),
response_uri: response_uri.to_string(),
contents: (contents),
},
))
}
pub fn parse_incomplete(i: &[u8]) -> AMFResult<'_, Packet> {
let (i, _) = tag([0u8].as_slice())(i)?;
let (i, version) = alt((
tag([FORMAT_VERSION_AMF0].as_slice()),
tag([FORMAT_VERSION_AMF3].as_slice()),
))
.parse(i)?;
let version: AMFVersion = version[0].try_into().expect("Invalid version");
let (i, headers) = length_count(be_u16, parse_header).parse(i)?;
let (i, messages) = length_count(be_u16, parse_message).parse(i)?;
Ok((
i,
Packet {
version,
headers,
messages,
},
))
}
pub fn parse(i: &[u8]) -> Result<Packet, nom::Err<Error<'_>>> {
let (_, packet) = all_consuming(|i| parse_incomplete(i)).parse(i)?;
Ok(packet)
}