oddity_rtsp_protocol/
rtp_info.rs

1use std::fmt;
2use std::str::FromStr;
3
4use super::Error;
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct RtpInfo {
8    pub url: String,
9    pub seq: Option<u16>,
10    pub rtptime: Option<u32>,
11}
12
13impl RtpInfo {
14    pub fn new(url: &str) -> Self {
15        RtpInfo {
16            url: url.to_string(),
17            seq: None,
18            rtptime: None,
19        }
20    }
21
22    pub fn new_with_timing(url: &str, seq: u16, rtptime: u32) -> Self {
23        RtpInfo {
24            url: url.to_string(),
25            seq: Some(seq),
26            rtptime: Some(rtptime),
27        }
28    }
29
30    pub fn with_seq(mut self, seq: u16) -> Self {
31        self.seq = Some(seq);
32        self
33    }
34
35    pub fn with_rtptime(mut self, rtptime: u32) -> Self {
36        self.rtptime = Some(rtptime);
37        self
38    }
39}
40
41impl fmt::Display for RtpInfo {
42    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43        write!(f, "url={}", self.url)?;
44        if let Some(seq) = self.seq {
45            write!(f, ";seq={}", seq)?;
46        }
47        if let Some(rtptime) = self.rtptime {
48            write!(f, ";rtptime={}", rtptime)?;
49        }
50        Ok(())
51    }
52}
53
54impl FromStr for RtpInfo {
55    type Err = Error;
56
57    fn from_str(s: &str) -> Result<Self, Self::Err> {
58        fn parse_parameter(part: &str, rtp_info: &mut RtpInfo) -> Result<(), Error> {
59            if let Some(seq) = part.strip_prefix("seq=") {
60                let seq = seq.parse().map_err(|_| Error::RtpInfoParameterInvalid {
61                    value: part.to_string(),
62                })?;
63                rtp_info.seq = Some(seq);
64                Ok(())
65            } else if let Some(rtptime) = part.strip_prefix("rtptime=") {
66                let rtptime = rtptime
67                    .parse()
68                    .map_err(|_| Error::RtpInfoParameterInvalid {
69                        value: part.to_string(),
70                    })?;
71                rtp_info.rtptime = Some(rtptime);
72                Ok(())
73            } else {
74                Err(Error::RtpInfoParameterUnknown {
75                    value: part.to_string(),
76                })
77            }
78        }
79
80        let mut parts = s.split(';');
81        if let Some(url) = parts.next() {
82            if let Some(url) = url.strip_prefix("url=") {
83                let mut rtp_info = RtpInfo::new(url);
84                if let Some(part) = parts.next() {
85                    parse_parameter(part, &mut rtp_info)?;
86                    if let Some(part) = parts.next() {
87                        parse_parameter(part, &mut rtp_info)?;
88                        match parts.next() {
89                            None => Ok(rtp_info),
90                            Some(part) => Err(Error::RtpInfoParameterUnexpected {
91                                value: part.to_string(),
92                            }),
93                        }
94                    } else {
95                        Ok(rtp_info)
96                    }
97                } else {
98                    Ok(rtp_info)
99                }
100            } else {
101                Err(Error::RtpInfoParameterUnknown {
102                    value: url.to_string(),
103                })
104            }
105        } else {
106            Err(Error::RtpInfoUrlMissing {
107                value: s.to_string(),
108            })
109        }
110    }
111}