1use std::{
4 borrow::Cow,
5 convert::Infallible,
6 fmt::{self, Display, Formatter},
7 ops::{Deref, DerefMut},
8 str::FromStr,
9};
10
11use str_reader::StringReader;
12
13use crate::ParseError;
14
15#[derive(Debug, Clone)]
17pub struct Attribute {
18 name: String,
19 value: Option<String>,
20}
21
22impl Attribute {
23 #[inline]
25 pub fn new_flag<N>(name: N) -> Self
26 where
27 N: ToString,
28 {
29 Self {
30 name: name.to_string(),
31 value: None,
32 }
33 }
34
35 #[inline]
37 pub fn new_attribute<N, V>(name: N, value: V) -> Self
38 where
39 N: ToString,
40 V: ToString,
41 {
42 Self {
43 name: name.to_string(),
44 value: Some(value.to_string()),
45 }
46 }
47
48 #[inline]
50 pub fn name(&self) -> &str {
51 &self.name
52 }
53
54 #[inline]
56 pub fn value(&self) -> Option<&str> {
57 self.value.as_deref()
58 }
59}
60
61impl Display for Attribute {
62 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
63 f.write_str(&self.name)?;
64
65 if let Some(v) = self.value.as_ref() {
66 write!(f, ":{}", v)?;
67 }
68
69 Ok(())
70 }
71}
72
73impl FromStr for Attribute {
74 type Err = Infallible;
75
76 fn from_str(s: &str) -> Result<Self, Self::Err> {
77 let (name, value) = if let Some(colon) = s.find(':') {
78 let (name, rest) = s.split_at(colon);
79
80 let value = &rest[1..];
81
82 (name, Some(value))
83 } else {
84 (s, None)
85 };
86
87 let res = Self {
88 name: name.to_string(),
89 value: value.map(|v| v.to_string()),
90 };
91
92 Ok(res)
93 }
94}
95
96#[derive(Clone)]
98pub struct Attributes {
99 inner: Vec<Attribute>,
100}
101
102impl Attributes {
103 #[inline]
105 pub const fn new() -> Self {
106 Self { inner: Vec::new() }
107 }
108
109 #[inline]
111 pub fn find<F>(&self, predicate: F) -> Option<&Attribute>
112 where
113 F: FnMut(&Attribute) -> bool,
114 {
115 self.find_all(predicate).next()
116 }
117
118 #[inline]
120 pub fn find_all<F>(&self, predicate: F) -> PredicateMatchingIter<'_, F>
121 where
122 F: FnMut(&Attribute) -> bool,
123 {
124 PredicateMatchingIter::new(self, predicate)
125 }
126
127 #[inline]
129 pub fn get(&self, name: &str) -> Option<&Attribute> {
130 self.find(|a| a.name() == name)
131 }
132
133 #[inline]
135 pub fn get_all<'a>(&'a self, name: &'a str) -> NameMatchingIter<'a> {
136 NameMatchingIter::new(self, name)
137 }
138
139 #[inline]
142 pub fn get_value(&self, name: &str) -> Option<&str> {
143 self.get(name).and_then(|a| a.value())
144 }
145
146 #[inline]
148 pub fn contains(&self, name: &str) -> bool {
149 self.get(name).is_some()
150 }
151}
152
153impl Default for Attributes {
154 #[inline]
155 fn default() -> Self {
156 Self::new()
157 }
158}
159
160impl Deref for Attributes {
161 type Target = Vec<Attribute>;
162
163 #[inline]
164 fn deref(&self) -> &Self::Target {
165 &self.inner
166 }
167}
168
169impl DerefMut for Attributes {
170 #[inline]
171 fn deref_mut(&mut self) -> &mut Self::Target {
172 &mut self.inner
173 }
174}
175
176pub struct PredicateMatchingIter<'a, F> {
178 predicate: F,
179 attributes: std::slice::Iter<'a, Attribute>,
180}
181
182impl<'a, F> PredicateMatchingIter<'a, F> {
183 fn new(attributes: &'a [Attribute], predicate: F) -> Self {
185 Self {
186 predicate,
187 attributes: attributes.iter(),
188 }
189 }
190}
191
192impl<'a, F> Iterator for PredicateMatchingIter<'a, F>
193where
194 F: FnMut(&Attribute) -> bool,
195{
196 type Item = &'a Attribute;
197
198 #[inline]
199 fn next(&mut self) -> Option<Self::Item> {
200 loop {
201 if let Some(item) = self.attributes.next() {
202 if (self.predicate)(item) {
203 return Some(item);
204 }
205 } else {
206 return None;
207 }
208 }
209 }
210}
211
212pub struct NameMatchingIter<'a> {
214 name: &'a str,
215 attributes: std::slice::Iter<'a, Attribute>,
216}
217
218impl<'a> NameMatchingIter<'a> {
219 fn new(attributes: &'a [Attribute], name: &'a str) -> Self {
221 Self {
222 name,
223 attributes: attributes.iter(),
224 }
225 }
226}
227
228impl<'a> Iterator for NameMatchingIter<'a> {
229 type Item = &'a Attribute;
230
231 #[inline]
232 fn next(&mut self) -> Option<Self::Item> {
233 loop {
234 if let Some(item) = self.attributes.next() {
235 if item.name() == self.name {
236 return Some(item);
237 }
238 } else {
239 return None;
240 }
241 }
242 }
243}
244
245#[derive(Clone)]
247pub struct RTPMap<'a> {
248 payload_type: u8,
249 encoding_name: &'a str,
250 clock_rate: u32,
251 encoding_parameters: Option<Cow<'a, str>>,
252}
253
254impl<'a> RTPMap<'a> {
255 #[inline]
257 pub const fn new(payload_type: u8, encoding_name: &'a str, clock_rate: u32) -> Self {
258 Self {
259 payload_type,
260 encoding_name,
261 clock_rate,
262 encoding_parameters: None,
263 }
264 }
265
266 #[inline]
268 pub fn with_encoding_parameters<T>(mut self, params: T) -> Self
269 where
270 T: ToString,
271 {
272 self.encoding_parameters = Some(Cow::Owned(params.to_string()));
273 self
274 }
275
276 #[inline]
278 pub fn payload_type(&self) -> u8 {
279 self.payload_type
280 }
281
282 #[inline]
284 pub fn encoding_name(&self) -> &str {
285 self.encoding_name
286 }
287
288 #[inline]
290 pub fn clock_rate(&self) -> u32 {
291 self.clock_rate
292 }
293
294 #[inline]
296 pub fn encoding_parameters(&self) -> Option<&str> {
297 self.encoding_parameters.as_deref()
298 }
299}
300
301impl<'a> Display for RTPMap<'a> {
302 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
303 write!(
304 f,
305 "{} {}/{}",
306 self.payload_type, self.encoding_name, self.clock_rate
307 )?;
308
309 if let Some(params) = self.encoding_parameters.as_ref() {
310 write!(f, "/{}", params)?;
311 }
312
313 Ok(())
314 }
315}
316
317impl<'a> TryFrom<&'a str> for RTPMap<'a> {
318 type Error = ParseError;
319
320 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
321 let mut reader = StringReader::new(s);
322
323 let payload_type = reader.read_u8()?;
324
325 reader.skip_whitespace();
326
327 let encoding_name = reader.read_until(|c| c == '/');
328
329 reader.match_char('/')?;
330
331 let clock_rate = reader.read_until(|c| c == '/').parse()?;
332
333 let encoding_parameters = if reader.is_empty() {
334 None
335 } else {
336 Some(Cow::Borrowed(&reader.as_str()[1..]))
337 };
338
339 let res = Self {
340 payload_type,
341 encoding_name,
342 clock_rate,
343 encoding_parameters,
344 };
345
346 Ok(res)
347 }
348}
349
350#[derive(Clone)]
352pub struct FormatParameters<'a> {
353 format: Cow<'a, str>,
354 params: Cow<'a, str>,
355}
356
357impl<'a> FormatParameters<'a> {
358 #[inline]
360 pub fn new<T, U>(format: T, parameters: U) -> Self
361 where
362 T: ToString,
363 U: ToString,
364 {
365 Self {
366 format: Cow::Owned(format.to_string()),
367 params: Cow::Owned(parameters.to_string()),
368 }
369 }
370
371 #[inline]
373 pub fn format(&self) -> &str {
374 &self.format
375 }
376
377 #[inline]
379 pub fn parameters(&self) -> &str {
380 &self.params
381 }
382}
383
384impl<'a> Display for FormatParameters<'a> {
385 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
386 write!(f, "{} {}", self.format, self.params)
387 }
388}
389
390impl<'a> From<&'a str> for FormatParameters<'a> {
391 fn from(s: &'a str) -> Self {
392 let s = s.trim();
393
394 let (format, params) = if let Some(space) = s.find(' ') {
395 let (f, r) = s.split_at(space);
396
397 let p = &r[1..];
398
399 (f, p)
400 } else {
401 (s, "")
402 };
403
404 Self {
405 format: Cow::Borrowed(format),
406 params: Cow::Borrowed(params),
407 }
408 }
409}