use std::convert::TryInto;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::number::complete::be_u32;
use crate::amf0;
use crate::amf0::read::AMF0Decoder;
#[cfg(feature = "amf3")]
use crate::amf3::read::AMF3Decoder;
use crate::errors::Error;
use crate::nom_utils::AMFResult;
use crate::types::{AMFVersion, Header, Lso};
use nom::Parser;
use nom::combinator::all_consuming;
const HEADER_VERSION: [u8; 2] = [0x00, 0xbf];
const HEADER_SIGNATURE: [u8; 10] = [0x54, 0x43, 0x53, 0x4f, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00];
const PADDING: [u8; 1] = [0x00];
const FORMAT_VERSION_AMF0: u8 = 0x0;
#[cfg(feature = "amf3")]
const FORMAT_VERSION_AMF3: u8 = 0x3;
#[derive(Default)]
pub struct Reader {
#[cfg(feature = "amf3")]
pub amf3_decoder: AMF3Decoder,
pub amf0_decoder: AMF0Decoder,
}
impl Reader {
pub fn parse_header<'a>(&self, i: &'a [u8]) -> AMFResult<'a, Header> {
let (i, _) = tag(HEADER_VERSION.as_slice())(i)?;
let (i, l) = be_u32(i)?;
let (i, _) = tag(HEADER_SIGNATURE.as_slice())(i)?;
let (i, name) = amf0::read::parse_string(i)?;
let (i, _) = tag(PADDING.as_slice())(i)?;
let (i, _) = tag(PADDING.as_slice())(i)?;
let (i, _) = tag(PADDING.as_slice())(i)?;
let (i, version) = alt((
tag([FORMAT_VERSION_AMF0].as_slice()),
#[cfg(feature = "amf3")]
tag([FORMAT_VERSION_AMF3].as_slice()),
))
.parse(i)?;
let format_version: AMFVersion = version[0].try_into().expect("Invalid version");
Ok((
i,
Header {
length: l,
name: name.to_string(),
format_version,
},
))
}
pub fn parse_incomplete<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Lso> {
let (i, header) = self.parse_header(i)?;
match header.format_version {
AMFVersion::AMF0 => {
let (i, body) = self.amf0_decoder.parse_body(i)?;
Ok((i, Lso { header, body }))
}
#[cfg(feature = "amf3")]
AMFVersion::AMF3 => {
let (i, body) = self.amf3_decoder.parse_body(i)?;
Ok((i, Lso { header, body }))
}
}
}
pub fn parse<'a>(&mut self, i: &'a [u8]) -> Result<Lso, nom::Err<Error<'a>>> {
let (_, lso) = all_consuming(|i| self.parse_incomplete(i)).parse(i)?;
Ok(lso)
}
}