sdp_nom/attributes/
extmap.rs

1//!<https://tools.ietf.org/html/rfc8285>
2
3use std::borrow::Cow;
4
5use derive_into_owned::IntoOwned;
6use nom::{
7    bytes::complete::tag,
8    combinator::{map, opt},
9    sequence::{preceded, tuple},
10    IResult,
11};
12
13use super::{read_direction, Direction};
14#[cfg(test)]
15use crate::assert_line;
16use crate::parsers::*;
17
18/// `a=extmap:<value>["/"<direction>] <URI> <extensionattributes>`
19///<https://tools.ietf.org/html/rfc8285#section-8>
20#[derive(Clone, IntoOwned, PartialEq, Eq)]
21#[cfg_attr(feature = "debug", derive(Debug))]
22#[cfg_attr(
23    feature = "serde",
24    derive(serde::Serialize, serde::Deserialize),
25    serde(rename_all = "camelCase")
26)]
27pub struct Extmap<'a> {
28    pub value: u32,
29    pub direction: Option<Direction>,
30    pub uri: Cow<'a, str>,
31    pub attributes: Vec<Cow<'a, str>>,
32}
33
34/// a=extmap:<value>["/"<direction>] <URI> <extensionattributes>
35fn read_extmap(input: &str) -> IResult<&str, Extmap> {
36    map(
37        tuple((
38            wsf(read_number),                             // <value>
39            wsf(opt(preceded(tag("/"), read_direction))), // ["/"<direction>]
40            wsf(cowify(read_string)),                     // <uri>
41            wsf(read_as_cow_strings),                     // <extensionattributes>
42        )),
43        |(value, direction, uri, attributes)| Extmap {
44            value,
45            direction,
46            uri,
47            attributes,
48        },
49    )(input)
50}
51
52pub fn extmap_line(input: &str) -> IResult<&str, Extmap> {
53    attribute("extmap", read_extmap)(input)
54}
55
56#[test]
57fn test_extmap() {
58    assert_line!(
59        read_extmap,
60        "1/sendonly URI-toffset",
61        Extmap {
62            value: 1,
63            direction: Some(Direction::SendOnly),
64            uri: "URI-toffset".into(),
65            attributes: vec![]
66        }
67    );
68    assert_line!(
69        read_extmap,
70        "2 urn:ietf:params:rtp-hdrext:toffset",
71        Extmap {
72            value: 2,
73            direction: None,
74            uri: "urn:ietf:params:rtp-hdrext:toffset".into(),
75            attributes: vec![]
76        }
77    );
78    assert_line!(
79        read_extmap,
80        "3 urn:ietf:params:rtp-hdrext:encrypt urn:ietf:params:rtp-hdrext:smpte-tc 25@600/24",
81        Extmap {
82            value: 3,
83            direction: None,
84            uri: "urn:ietf:params:rtp-hdrext:encrypt".into(),
85            attributes: vec![
86                "urn:ietf:params:rtp-hdrext:smpte-tc".into(),
87                "25@600/24".into()
88            ]
89        }
90    );
91    assert_line!(
92        read_extmap,
93        "4/recvonly urn:ietf:params:rtp-hdrext:encrypt URI-gps-string",
94        Extmap {
95            value: 4,
96            direction: Some(Direction::RecvOnly),
97            uri: "urn:ietf:params:rtp-hdrext:encrypt".into(),
98            attributes: vec!["URI-gps-string".into()]
99        }
100    );
101}
102#[test]
103fn test_extmap_line() {
104    assert_line!(extmap_line, "a=extmap:1/sendonly URI-toffset");
105    assert_line!(extmap_line, "a=extmap:2 urn:ietf:params:rtp-hdrext:toffset");
106    assert_line!(
107        extmap_line,
108        "a=extmap:3 urn:ietf:params:rtp-hdrext:encrypt urn:ietf:params:rtp-hdrext:smpte-tc 25@600/24"
109    );
110    assert_line!(
111        extmap_line,
112        "a=extmap:4/recvonly urn:ietf:params:rtp-hdrext:encrypt URI-gps-string"
113    );
114    assert_line!(
115        extmap_line,
116        "a=extmap:2/sendrecv http://example.com/082005/ext.htm#xmeta short"
117    );
118}