rtsp_types/headers/
supported.rs

1// Copyright (C) 2020 Sebastian Dröge <sebastian@centricular.com>
2//
3// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4
5use super::features::*;
6use super::*;
7
8/// `Supported` header ([RFC 7826 section 18.51](https://tools.ietf.org/html/rfc7826#section-18.51)).
9#[derive(Debug, Clone)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Supported(Vec<String>);
12
13impl std::ops::Deref for Supported {
14    type Target = Vec<String>;
15
16    fn deref(&self) -> &Self::Target {
17        &self.0
18    }
19}
20
21impl std::ops::DerefMut for Supported {
22    fn deref_mut(&mut self) -> &mut Self::Target {
23        &mut self.0
24    }
25}
26
27impl AsRef<Vec<String>> for Supported {
28    fn as_ref(&self) -> &Vec<String> {
29        &self.0
30    }
31}
32
33impl AsMut<Vec<String>> for Supported {
34    fn as_mut(&mut self) -> &mut Vec<String> {
35        &mut self.0
36    }
37}
38
39impl From<Vec<String>> for Supported {
40    fn from(v: Vec<String>) -> Self {
41        Supported(v)
42    }
43}
44
45impl<'a> From<&'a [String]> for Supported {
46    fn from(v: &'a [String]) -> Self {
47        Supported(v.to_vec())
48    }
49}
50
51impl<'a> From<&'a [&'a &str]> for Supported {
52    fn from(v: &'a [&'a &str]) -> Self {
53        Supported(v.iter().map(|s| String::from(**s)).collect())
54    }
55}
56
57impl Supported {
58    /// Creates a new `Supported` header builder.
59    pub fn builder() -> SupportedBuilder {
60        SupportedBuilder(Vec::new())
61    }
62
63    /// Check if the "play.basic" feature is supported.
64    ///
65    /// See [RFC 7826 section 11.1](https://tools.ietf.org/html/rfc7826#section-11.1).
66    pub fn contains_play_basic(&self) -> bool {
67        self.0.iter().any(|f| f == PLAY_BASIC)
68    }
69
70    /// Check if the "play.scale" feature is supported.
71    ///
72    /// See [RFC 7826 section 18.46](https://tools.ietf.org/html/rfc7826#section-18.46).
73    pub fn contains_play_scale(&self) -> bool {
74        self.0.iter().any(|f| f == PLAY_SCALE)
75    }
76
77    /// Check if the "play.speed" feature is supported.
78    ///
79    /// See [RFC 7826 section 18.50](https://tools.ietf.org/html/rfc7826#section-18.50).
80    pub fn contains_play_speed(&self) -> bool {
81        self.0.iter().any(|f| f == PLAY_SPEED)
82    }
83
84    /// Check if the "setup.rtp.rtcp.mux" feature is supported.
85    ///
86    /// See [RFC 7826 Appendix C.1.6.4](https://tools.ietf.org/html/rfc7826#appendix-C.1.6.4).
87    pub fn contains_setup_rtp_rtcp_mux(&self) -> bool {
88        self.0.iter().any(|f| f == SETUP_RTP_RTCP_MUX)
89    }
90}
91
92/// Builder for the 'Supported' header.
93#[derive(Debug, Clone)]
94pub struct SupportedBuilder(Vec<String>);
95
96impl SupportedBuilder {
97    /// Add the provided feature to the `Supported` header.
98    pub fn feature<S: Into<String>>(mut self, feature: S) -> Self {
99        self.0.push(feature.into());
100        self
101    }
102
103    /// Add the "play.basic" feature to the `Supported` header.
104    ///
105    /// See [RFC 7826 section 11.1](https://tools.ietf.org/html/rfc7826#section-11.1).
106    pub fn play_basic(self) -> Self {
107        self.feature(PLAY_BASIC)
108    }
109
110    /// Add the "play.scale" feature to the `Supported` header.
111    ///
112    /// See [RFC 7826 section 18.46](https://tools.ietf.org/html/rfc7826#section-18.46).
113    pub fn play_scale(self) -> Self {
114        self.feature(PLAY_SCALE)
115    }
116
117    /// Add the "play.speed" feature to the `Supported` header.
118    ///
119    /// See [RFC 7826 section 18.50](https://tools.ietf.org/html/rfc7826#section-18.50).
120    pub fn play_speed(self) -> Self {
121        self.feature(PLAY_SPEED)
122    }
123
124    /// Add the "setup.rtp.rtcp.mux" feature to the `Supported` header.
125    ///
126    /// See [RFC 7826 Appendix C.1.6.4](https://tools.ietf.org/html/rfc7826#appendix-C.1.6.4).
127    pub fn setup_rtp_rtcp_mux(self) -> Self {
128        self.feature(SETUP_RTP_RTCP_MUX)
129    }
130
131    /// Build the `Supported` header.
132    pub fn build(self) -> Supported {
133        Supported(self.0)
134    }
135}
136
137impl super::TypedHeader for Supported {
138    fn from_headers(headers: impl AsRef<Headers>) -> Result<Option<Self>, HeaderParseError> {
139        let headers = headers.as_ref();
140
141        let header = match headers.get(&SUPPORTED) {
142            None => return Ok(None),
143            Some(header) => header,
144        };
145
146        let mut supported = Vec::new();
147        for feature in header.as_str().split(',') {
148            let feature = feature.trim();
149
150            supported.push(feature.into());
151        }
152
153        Ok(Some(Supported(supported)))
154    }
155
156    fn insert_into(&self, mut headers: impl AsMut<Headers>) {
157        let headers = headers.as_mut();
158
159        let mut supported = String::new();
160        for feature in &self.0 {
161            if !supported.is_empty() {
162                supported.push_str(", ");
163            }
164
165            supported.push_str(feature);
166        }
167
168        headers.insert(SUPPORTED, supported);
169    }
170}
171
172impl super::TypedAppendableHeader for Supported {
173    fn append_to(&self, mut headers: impl AsMut<Headers>) {
174        let headers = headers.as_mut();
175
176        let mut supported = String::new();
177        for feature in &self.0 {
178            if !supported.is_empty() {
179                supported.push_str(", ");
180            }
181
182            supported.push_str(feature);
183        }
184
185        headers.append(SUPPORTED, supported);
186    }
187}