sdp_rs/tokenizers/
media.rs1use crate::TResult;
2
3#[derive(Debug, PartialEq, Eq, Clone)]
4pub struct Tokenizer<'a> {
5 pub media: &'a str,
6 pub port: PortTokenizer<'a>,
7 pub proto: &'a str,
8 pub fmt: &'a str,
9}
10
11impl<'a> Tokenizer<'a> {
12 pub fn tokenize(part: &'a str) -> TResult<'a, Self> {
13 use crate::parser_utils::*;
14 use nom::{bytes::complete::tag, sequence::preceded};
15
16 let (rem, line) = preceded(tag("m="), until_newline)(part)?;
17 let (line_rem, media) = until_space(line)?;
18 let (line_rem, port_with_num_of_ports) = until_space(line_rem)?;
19 let (fmt, proto) = until_space(line_rem)?;
20 let (_, port) = PortTokenizer::tokenize(port_with_num_of_ports)?;
21
22 Ok((
23 rem,
24 Tokenizer {
25 media,
26 port,
27 proto,
28 fmt,
29 },
30 ))
31 }
32}
33
34#[derive(Debug, PartialEq, Eq, Clone)]
35pub struct PortTokenizer<'a> {
36 pub port: &'a str,
37 pub num_of_ports: Option<&'a str>,
38}
39
40impl<'a> PortTokenizer<'a> {
41 pub fn tokenize(part: &'a str) -> TResult<'a, Self> {
42 use nom::{
43 branch::alt,
44 bytes::complete::{tag, take_until},
45 combinator::rest,
46 sequence::terminated,
47 };
48
49 let (num_of_ports, port) = alt((terminated(take_until("/"), tag("/")), rest))(part)?;
50 let num_of_ports = match num_of_ports.is_empty() {
51 true => None,
52 false => Some(num_of_ports),
53 };
54
55 Ok(("", (port, num_of_ports).into()))
56 }
57}
58
59impl<'a> From<(&'a str, Option<&'a str>)> for PortTokenizer<'a> {
60 fn from((port, num_of_ports): (&'a str, Option<&'a str>)) -> Self {
61 Self { port, num_of_ports }
62 }
63}
64
65impl<'a> From<(&'a str, &'a str)> for PortTokenizer<'a> {
66 fn from((port, num_of_ports): (&'a str, &'a str)) -> Self {
67 Self {
68 port,
69 num_of_ports: Some(num_of_ports),
70 }
71 }
72}
73
74impl<'a> From<&'a str> for PortTokenizer<'a> {
75 fn from(port: &'a str) -> Self {
76 Self {
77 port,
78 num_of_ports: None,
79 }
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn tokenizer1() {
89 let media = concat!("m=audio 49170 RTP/AVP 0\r\nsomething");
90
91 assert_eq!(
92 Tokenizer::tokenize(media),
93 Ok((
94 "something",
95 Tokenizer {
96 media: "audio",
97 port: ("49170", None).into(),
98 proto: "RTP/AVP",
99 fmt: "0",
100 }
101 )),
102 );
103 }
104
105 #[test]
106 fn tokenizer2() {
107 let media = concat!("m=video 49170/2 RTP/AVP 31\r\nsomething");
108
109 assert_eq!(
110 Tokenizer::tokenize(media),
111 Ok((
112 "something",
113 Tokenizer {
114 media: "video",
115 port: ("49170", "2").into(),
116 proto: "RTP/AVP",
117 fmt: "31",
118 }
119 )),
120 );
121 }
122}