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::amf0::read::AMF0Decoder;
9#[cfg(feature = "amf3")]
10use crate::amf3::read::AMF3Decoder;
11use crate::errors::Error;
12use crate::nom_utils::AMFResult;
13use crate::types::{AMFVersion, Header, Lso};
14use nom::Parser;
15use nom::combinator::all_consuming;
16
17const HEADER_VERSION: [u8; 2] = [0x00, 0xbf];
18const HEADER_SIGNATURE: [u8; 10] = [0x54, 0x43, 0x53, 0x4f, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00];
19const PADDING: [u8; 1] = [0x00];
20
21const FORMAT_VERSION_AMF0: u8 = 0x0;
22
23#[cfg(feature = "amf3")]
24const FORMAT_VERSION_AMF3: u8 = 0x3;
25
26#[derive(Default)]
40pub struct Reader {
41 #[cfg(feature = "amf3")]
42 pub amf3_decoder: AMF3Decoder,
44
45 pub amf0_decoder: AMF0Decoder,
47}
48
49impl Reader {
50 pub fn parse_header<'a>(&self, i: &'a [u8]) -> AMFResult<'a, Header> {
52 let (i, _) = tag(HEADER_VERSION.as_slice())(i)?;
53 let (i, l) = be_u32(i)?;
54 let (i, _) = tag(HEADER_SIGNATURE.as_slice())(i)?;
55
56 let (i, name) = amf0::read::parse_string(i)?;
57
58 let (i, _) = tag(PADDING.as_slice())(i)?;
59 let (i, _) = tag(PADDING.as_slice())(i)?;
60 let (i, _) = tag(PADDING.as_slice())(i)?;
61
62 let (i, version) = alt((
63 tag([FORMAT_VERSION_AMF0].as_slice()),
64 #[cfg(feature = "amf3")]
65 tag([FORMAT_VERSION_AMF3].as_slice()),
66 ))
67 .parse(i)?;
68
69 let format_version: AMFVersion = version[0].try_into().expect("Invalid version");
71
72 Ok((
73 i,
74 Header {
75 length: l,
76 name: name.to_string(),
77 format_version,
78 },
79 ))
80 }
81
82 pub fn parse_incomplete<'a>(&mut self, i: &'a [u8]) -> AMFResult<'a, Lso> {
87 let (i, header) = self.parse_header(i)?;
88 match header.format_version {
89 AMFVersion::AMF0 => {
90 let (i, body) = self.amf0_decoder.parse_body(i)?;
91 Ok((i, Lso { header, body }))
92 }
93
94 #[cfg(feature = "amf3")]
95 AMFVersion::AMF3 => {
96 let (i, body) = self.amf3_decoder.parse_body(i)?;
97 Ok((i, Lso { header, body }))
98 }
99 }
100 }
101
102 pub fn parse<'a>(&mut self, i: &'a [u8]) -> Result<Lso, nom::Err<Error<'a>>> {
107 let (_, lso) = all_consuming(|i| self.parse_incomplete(i)).parse(i)?;
108 Ok(lso)
109 }
110}