oddity_rtsp_protocol/
rtp_info.rs1use 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}