1use std::borrow::Cow;
2
3use derive_into_owned::IntoOwned;
4use nom::{
5 branch::alt,
6 bytes::complete::{is_not, tag},
7 character::complete::multispace0,
8 combinator::map,
9 sequence::{preceded, separated_pair, tuple},
10 IResult,
11};
12
13use crate::parsers::*;
14#[cfg(test)]
15use crate::{assert_line, assert_line_print};
16
17#[derive(Clone, IntoOwned, PartialEq, Eq)]
18#[cfg_attr(feature = "debug", derive(Debug))]
19#[cfg_attr(
20 feature = "serde",
21 derive(serde::Serialize, serde::Deserialize),
22 serde(rename_all = "camelCase")
23)]
24pub struct Ssrc<'a> {
25 pub id: u64,
26 pub attribute: Cow<'a, str>,
27 pub value: Cow<'a, str>,
28}
29
30pub fn ssrc_line(input: &str) -> IResult<&str, Ssrc> {
32 attribute(
33 "ssrc",
34 map(
35 tuple((
36 wsf(read_big_number), preceded(
38 multispace0,
39 separated_pair(
40 cowify(read_non_colon_string),
41 tag(":"),
42 cowify(wsf(is_not("\n"))),
43 ),
44 ),
45 )),
46 |(id, (attribute, value))| Ssrc {
47 id,
48 attribute,
49 value,
50 },
51 ),
52 )(input)
53}
54
55#[test]
56#[rustfmt::skip]
57fn test_ssrc_line() {
58 assert_line!(
59 ssrc_line,
60 "a=ssrc:1366781084 cname:EocUG1f0fcg/yvY7",
61 Ssrc { id: 1366781084, attribute: "cname".into(), value: "EocUG1f0fcg/yvY7".into() },
62 print
63 );
64 assert_line!(
65 ssrc_line,
66 "a=ssrc: 1366781084 cname: EocUG1f0fcg/yvY7",
67 Ssrc { id: 1366781084, attribute: "cname".into(), value: "EocUG1f0fcg/yvY7".into() }
68 );
69 assert_line!(ssrc_line, "a=ssrc:3570614608 cname:4TOk42mSjXCkVIa6");
70 assert_line!(ssrc_line, "a=ssrc:3570614608 msid:lgsCFqt9kN2fVKw5wg3NKqGdATQoltEwOdMS 35429d94-5637-4686-9ecd-7d0622261ce8");
71 assert_line!(ssrc_line, "a=ssrc:3570614608 mslabel:lgsCFqt9kN2fVKw5wg3NKqGdATQoltEwOdMS");
72 assert_line!(ssrc_line, "a=ssrc:3570614608 label:35429d94-5637-4686-9ecd-7d0622261ce8");
73 assert_line!(ssrc_line, "a=ssrc:2231627014 cname:4TOk42mSjXCkVIa6");
74 assert_line!(ssrc_line, "a=ssrc:2231627014 msid:lgsCFqt9kN2fVKw5wg3NKqGdATQoltEwOdMS daed9400-d0dd-4db3-b949-422499e96e2d");
75 assert_line!(ssrc_line, "a=ssrc:2231627014 mslabel:lgsCFqt9kN2fVKw5wg3NKqGdATQoltEwOdMS");
76 assert_line!(ssrc_line, "a=ssrc:2231627014 label:daed9400-d0dd-4db3-b949-422499e96e2d");
77 assert_line!(ssrc_line, "a=ssrc:632943048 cname:4TOk42mSjXCkVIa6");
78 assert_line!(ssrc_line, "a=ssrc:632943048 msid:lgsCFqt9kN2fVKw5wg3NKqGdATQoltEwOdMS daed9400-d0dd-4db3-b949-422499e96e2d");
79}
80
81#[derive(Clone, PartialEq, Eq)]
82#[cfg_attr(feature = "debug", derive(Debug))]
83#[cfg_attr(
84 feature = "serde",
85 derive(serde::Serialize, serde::Deserialize),
86 serde(rename_all = "camelCase")
87)]
88#[non_exhaustive]
89pub enum SsrcSemantic {
90 FID,
91 FEC,
92}
93
94#[derive(Clone, PartialEq, Eq)]
95#[cfg_attr(feature = "debug", derive(Debug))]
96#[cfg_attr(
97 feature = "serde",
98 derive(serde::Serialize, serde::Deserialize),
99 serde(rename_all = "camelCase")
100)]
101pub struct SsrcGroup {
102 pub semantic: SsrcSemantic,
103 pub ids: Vec<u32>,
104}
105
106pub fn ssrc_group_line(input: &str) -> IResult<&str, SsrcGroup> {
107 attribute("ssrc-group", ssrc_group)(input)
108}
109
110pub fn ssrc_group(input: &str) -> IResult<&str, SsrcGroup> {
111 map(
112 tuple((
113 alt((
114 map(tag("FID"), |_| SsrcSemantic::FID),
116 map(tag("FEC"), |_| SsrcSemantic::FEC),
117 )),
118 wsf(read_as_numbers), )),
120 |(semantic, ids)| SsrcGroup { semantic, ids },
121 )(input)
122}
123
124#[test]
125#[rustfmt::skip]
126fn test_ssrc_group_line() {
127 assert_line_print!(ssrc_group_line, "a=ssrc-group:FID 2231627014 632943048");
128}