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
267impl RTPMap<'_> {
268 #[inline]
270 pub fn with_encoding_parameters<T>(mut self, params: T) -> Self
271 where
272 T: ToString,
273 {
274 self.encoding_parameters = Some(Cow::Owned(params.to_string()));
275 self
276 }
277
278 #[inline]
280 pub fn payload_type(&self) -> u8 {
281 self.payload_type
282 }
283
284 #[inline]
286 pub fn encoding_name(&self) -> &str {
287 self.encoding_name
288 }
289
290 #[inline]
292 pub fn clock_rate(&self) -> u32 {
293 self.clock_rate
294 }
295
296 #[inline]
298 pub fn encoding_parameters(&self) -> Option<&str> {
299 self.encoding_parameters.as_deref()
300 }
301}
302
303impl Display for RTPMap<'_> {
304 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
305 write!(
306 f,
307 "{} {}/{}",
308 self.payload_type, self.encoding_name, self.clock_rate
309 )?;
310
311 if let Some(params) = self.encoding_parameters.as_ref() {
312 write!(f, "/{params}")?;
313 }
314
315 Ok(())
316 }
317}
318
319impl<'a> TryFrom<&'a str> for RTPMap<'a> {
320 type Error = ParseError;
321
322 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
323 let mut reader = StringReader::new(s);
324
325 let payload_type = reader.read_u8()?;
326
327 reader.skip_whitespace();
328
329 let encoding_name = reader.read_until(|c| c == '/');
330
331 reader.match_char('/')?;
332
333 let clock_rate = reader.read_until(|c| c == '/').parse()?;
334
335 let encoding_parameters = if reader.is_empty() {
336 None
337 } else {
338 Some(Cow::Borrowed(&reader.as_str()[1..]))
339 };
340
341 let res = Self {
342 payload_type,
343 encoding_name,
344 clock_rate,
345 encoding_parameters,
346 };
347
348 Ok(res)
349 }
350}
351
352#[derive(Clone)]
354pub struct FormatParameters<'a> {
355 format: Cow<'a, str>,
356 params: Cow<'a, str>,
357}
358
359impl FormatParameters<'_> {
360 #[inline]
362 pub fn new<T, U>(format: T, parameters: U) -> Self
363 where
364 T: ToString,
365 U: ToString,
366 {
367 Self {
368 format: Cow::Owned(format.to_string()),
369 params: Cow::Owned(parameters.to_string()),
370 }
371 }
372
373 #[inline]
375 pub fn format(&self) -> &str {
376 &self.format
377 }
378
379 #[inline]
381 pub fn parameters(&self) -> &str {
382 &self.params
383 }
384}
385
386impl Display for FormatParameters<'_> {
387 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
388 write!(f, "{} {}", self.format, self.params)
389 }
390}
391
392impl<'a> From<&'a str> for FormatParameters<'a> {
393 fn from(s: &'a str) -> Self {
394 let s = s.trim();
395
396 let (format, params) = if let Some(space) = s.find(' ') {
397 let (f, r) = s.split_at(space);
398
399 let p = &r[1..];
400
401 (f, p)
402 } else {
403 (s, "")
404 };
405
406 Self {
407 format: Cow::Borrowed(format),
408 params: Cow::Borrowed(params),
409 }
410 }
411}