1use nom::{
2 IResult,
3 branch::alt,
4 bytes::complete::{tag,take_until},
5 combinator::{map, map_res},
6};
7
8use crate::parse::slice_to_string;
9use crate::parse::ParserResult;
10
11mod ty;
12pub use self::ty::SdpAttributeType;
13pub use self::ty::parse_attribute_type;
14
15mod optional;
16pub use self::optional::SdpOptionalAttribute;
17pub use self::optional::parse_optional_attributes;
18
19use std::fmt;
20
21mod rtpmap;
22pub use self::rtpmap::RtpMap;
23pub use self::rtpmap::parse_rtpmap;
24
25
26#[derive(Debug, PartialEq, Clone)]
27pub enum SdpAttribute {
28 SendOnly,
29 RecvOnly,
30 SendRecv,
31 RtpMap(RtpMap),
32 Fmtp(String)
33}
34
35pub fn parse_global_attribute(input: &[u8]) -> IResult<&[u8], SdpAttribute> {
36 alt((
37 map(tag("a=sendrecv"), |_| SdpAttribute::SendOnly),
38 map(tag("a=recvonly"), |_| SdpAttribute::RecvOnly),
39 map(tag("a=sendrecv"), |_| SdpAttribute::SendRecv),
40 parse_rtpmap_attribute,
41 parse_fmtp_attribute
42 ))(input)
43}
44
45pub fn parse_rtpmap_attribute(input: &[u8]) -> IResult<&[u8], SdpAttribute> {
46 let (input, _) = tag("a=rtpmap ")(input)?;
47 let (input, data) = parse_rtpmap(input)?;
48 Ok((input, SdpAttribute::RtpMap(data)))
49}
50
51pub fn parse_fmtp_attribute(input: &[u8]) -> IResult<&[u8], SdpAttribute> {
52 let (input, _) = tag("a=fmtp ")(input)?;
53 let (input, data) = map_res(take_until("\r"), slice_to_string)(input)?;
54 Ok((input, SdpAttribute::Fmtp(data)))
55}
56
57pub fn parse_global_attributes(input: &[u8]) -> ParserResult<Vec<SdpAttribute>> {
58 let mut output = vec![];
59 let mut data = input;
60 while let Ok((remains, attribute)) = parse_global_attribute(data) {
61 output.push(attribute);
62 data = remains;
63 }
64 Ok((data, output))
65}
66
67impl fmt::Display for SdpAttribute {
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 match self {
70 SdpAttribute::RecvOnly => write!(f, "recvonly"),
71 SdpAttribute::SendOnly => write!(f, "sendonly"),
72 SdpAttribute::SendRecv => write!(f, "sendrecv"),
73 SdpAttribute::RtpMap(data) => write!(f, "rtpmap {}", data),
74 SdpAttribute::Fmtp(data) => write!(f, "fmtp {}", data)
75 }
76 }
77}