Skip to main content

flowly_flv/parser/tag/
meta.rs

1use std::collections::HashMap;
2
3use bytes::Bytes;
4
5use crate::{
6    error::Error,
7    parser::{FlvParser, Parser},
8    reader::FlvReader,
9    tag::meta::{MetaDataDate, MetaDataValue, MetaTag},
10};
11
12const OBJECT_END_MARKER: [u8; 3] = [0x00, 0x00, 0x09];
13
14impl<E> Parser<E, MetaTag> for FlvParser {
15    type Error = Error<E>;
16
17    /// Parse script tag data.
18    fn parse(&mut self, reader: &mut impl FlvReader) -> Result<MetaTag, Self::Error> {
19        let _tag = reader.read_u8()?;
20        let name = self.parse_meta_string(reader)?;
21
22        // AMF arguments or object properties.
23        Ok(MetaTag {
24            name,
25            value: self.parse(reader)?,
26        })
27    }
28}
29
30impl FlvParser {
31    #[inline]
32    fn parse_meta_string<E>(&mut self, reader: &mut impl FlvReader) -> Result<Bytes, Error<E>> {
33        let len = reader.read_u16()? as usize;
34
35        Ok(reader.read_to_bytes(len as usize)?)
36    }
37
38    fn parse_meta_object<E>(
39        &mut self,
40        reader: &mut impl FlvReader,
41    ) -> Result<HashMap<Bytes, MetaDataValue>, Error<E>> {
42        let mut props = HashMap::new();
43
44        while reader.available() >= 3 && reader.peek(0..3)? != OBJECT_END_MARKER {
45            props.insert(self.parse_meta_string(reader)?, self.parse(reader)?);
46        }
47
48        Ok(props)
49    }
50}
51
52impl<E> Parser<E, MetaDataValue> for FlvParser {
53    type Error = Error<E>;
54
55    /// Parse script tag data value.
56    fn parse(&mut self, reader: &mut impl FlvReader) -> Result<MetaDataValue, Self::Error> {
57        Ok(match reader.read_u8()? {
58            0 => MetaDataValue::Number(reader.read_f64()?),
59            1 => MetaDataValue::Boolean(reader.read_u8()? != 0),
60            2 => MetaDataValue::String(self.parse_meta_string(reader)?),
61            3 => MetaDataValue::Object(self.parse_meta_object(reader)?),
62            5 => MetaDataValue::Null,
63            6 => MetaDataValue::Undefined,
64            7 => MetaDataValue::Reference(reader.read_u16()?),
65            8 => {
66                let _len = reader.read_u32()?;
67                MetaDataValue::ECMAArray(self.parse_meta_object(reader)?)
68            }
69            10 => {
70                let len = reader.read_u32()?;
71                let mut arr = Vec::with_capacity(len as usize);
72                for _ in 0..len {
73                    arr.push(self.parse(reader)?);
74                }
75
76                MetaDataValue::StrictArray(arr)
77            }
78            11 => MetaDataValue::Date(MetaDataDate {
79                date_time: reader.read_f64()?,
80                local_date_time_offset: reader.read_i16()?,
81            }),
82            12 => {
83                let len = reader.read_u32()? as usize;
84
85                MetaDataValue::LongString(reader.read_to_bytes(len)?)
86            }
87            id => MetaDataValue::Unknown(id),
88        })
89    }
90}