sdp_rs/lines/media/
mod.rs

1//! Types related to the media line (`m=`).
2
3mod media_type;
4mod proto_type;
5
6/// The media line (`m=`) tokenizer. This is low level stuff and you shouldn't interact directly
7/// with it, unless you know what you are doing.
8pub use crate::tokenizers::media::Tokenizer;
9pub use media_type::MediaType;
10pub use proto_type::ProtoType;
11
12use crate::Error;
13use std::convert::TryFrom;
14
15/// A media line (`m=`) of SDP. Media is part of the high level [crate::MediaDescription] type.
16#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)]
17pub struct Media {
18    pub media: MediaType,
19    pub port: u16,
20    pub num_of_ports: Option<u8>,
21    pub proto: ProtoType,
22    pub fmt: String,
23}
24
25impl<'a> TryFrom<Tokenizer<'a>> for Media {
26    type Error = Error;
27
28    fn try_from(tokenizer: Tokenizer<'a>) -> Result<Self, Self::Error> {
29        Ok(Self {
30            media: tokenizer.media.into(),
31            port: tokenizer.port.port.parse().map_err(|e| {
32                Self::Error::parser_with_error("media port", tokenizer.port.port, e)
33            })?,
34            num_of_ports: tokenizer
35                .port
36                .num_of_ports
37                .map(|num| {
38                    num.parse()
39                        .map_err(|e| Self::Error::parser_with_error("media num of ports", num, e))
40                })
41                .transpose()?,
42            proto: tokenizer.proto.into(),
43            fmt: tokenizer.fmt.into(),
44        })
45    }
46}
47
48impl std::fmt::Display for Media {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        match self.num_of_ports {
51            Some(num_of_ports) => write!(
52                f,
53                "{} {}/{} {} {}",
54                self.media, self.port, num_of_ports, self.proto, self.fmt
55            ),
56            None => write!(
57                f,
58                "{} {} {} {}",
59                self.media, self.port, self.proto, self.fmt
60            ),
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn from_tokenizer1() {
71        let tokenizer = Tokenizer {
72            media: "audio",
73            port: ("49170", "2").into(),
74            proto: "RTP/AVP",
75            fmt: "0",
76        };
77
78        assert_eq!(
79            Media::try_from(tokenizer),
80            Ok(Media {
81                media: MediaType::Audio,
82                port: 49170,
83                num_of_ports: Some(2),
84                proto: ProtoType::RtpAvp,
85                fmt: "0".into(),
86            })
87        );
88    }
89
90    #[test]
91    fn display1() {
92        assert_eq!(
93            Media {
94                media: MediaType::Audio,
95                port: 49170,
96                num_of_ports: Some(2),
97                proto: ProtoType::RtpAvp,
98                fmt: "0".into(),
99            }
100            .to_string(),
101            "audio 49170/2 RTP/AVP 0"
102        );
103    }
104}