1use std::{
4 borrow::{Borrow, BorrowMut, ToOwned},
5 ffi::CStr,
6 fmt, mem, ops, ptr,
7};
8
9use glib::translate::*;
10
11use crate::{
12 ffi, sdp_attribute::SDPAttribute, sdp_bandwidth::SDPBandwidth, sdp_connection::SDPConnection,
13 sdp_key::SDPKey,
14};
15
16glib::wrapper! {
17 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
18 #[doc(alias = "GstSDPMedia")]
19 pub struct SDPMedia(Boxed<ffi::GstSDPMedia>);
20
21 match fn {
22 copy => |ptr| {
23 let mut copy = ptr::null_mut();
24 let res = ffi::gst_sdp_media_copy(ptr, &mut copy);
25 debug_assert_eq!(res, ffi::GST_SDP_OK);
26 copy
27 },
28 free => |ptr| {
29 let res = ffi::gst_sdp_media_free(ptr);
30 debug_assert_eq!(res, ffi::GST_SDP_OK);
31 },
32 }
33}
34
35impl SDPMedia {
36 #[doc(alias = "gst_sdp_media_new")]
37 pub fn new() -> Self {
38 assert_initialized_main_thread!();
39 unsafe {
40 let mut media = ptr::null_mut();
41 ffi::gst_sdp_media_new(&mut media);
42 from_glib_full(media)
43 }
44 }
45}
46
47impl Default for SDPMedia {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53unsafe impl Send for SDPMedia {}
54unsafe impl Sync for SDPMedia {}
55
56impl ops::Deref for SDPMedia {
57 type Target = SDPMediaRef;
58
59 fn deref(&self) -> &SDPMediaRef {
60 unsafe { &*(self.as_ptr() as *const SDPMediaRef) }
61 }
62}
63
64impl ops::DerefMut for SDPMedia {
65 fn deref_mut(&mut self) -> &mut SDPMediaRef {
66 unsafe { &mut *(self.to_glib_none_mut().0 as *mut SDPMediaRef) }
67 }
68}
69
70impl fmt::Debug for SDPMedia {
71 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 <SDPMediaRef as fmt::Debug>::fmt(self, f)
73 }
74}
75
76impl fmt::Display for SDPMedia {
77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 <SDPMediaRef as fmt::Display>::fmt(self, f)
79 }
80}
81
82#[repr(transparent)]
83#[doc(alias = "GstSDPMedia")]
84pub struct SDPMediaRef(ffi::GstSDPMedia);
85
86impl fmt::Debug for SDPMediaRef {
87 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88 use std::cell::RefCell;
89
90 struct DebugIter<I>(RefCell<I>);
91 impl<I: Iterator> fmt::Debug for DebugIter<I>
92 where
93 I::Item: fmt::Debug,
94 {
95 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96 f.debug_list().entries(&mut *self.0.borrow_mut()).finish()
97 }
98 }
99
100 f.debug_struct("SDPMedia")
101 .field("formats", &DebugIter(RefCell::new(self.formats())))
102 .field("connections", &DebugIter(RefCell::new(self.connections())))
103 .field("bandwidths", &DebugIter(RefCell::new(self.bandwidths())))
104 .field("attributes", &DebugIter(RefCell::new(self.attributes())))
105 .field("information", &self.information())
106 .field("key", &self.key())
107 .field("media", &self.media())
108 .field("port", &self.port())
109 .field("num-ports", &self.num_ports())
110 .field("proto", &self.proto())
111 .finish()
112 }
113}
114
115impl fmt::Display for SDPMediaRef {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 match self.as_text() {
118 Ok(text) => f.write_str(text.as_str()),
119 Err(_) => Err(fmt::Error),
120 }
121 }
122}
123
124unsafe impl Send for SDPMediaRef {}
125unsafe impl Sync for SDPMediaRef {}
126
127impl SDPMediaRef {
128 #[doc(alias = "gst_sdp_media_add_attribute")]
129 pub fn add_attribute(&mut self, key: &str, value: Option<&str>) {
130 let value = value.to_glib_none();
131 unsafe { ffi::gst_sdp_media_add_attribute(&mut self.0, key.to_glib_none().0, value.0) };
132 }
133
134 #[doc(alias = "gst_sdp_media_add_bandwidth")]
135 pub fn add_bandwidth(&mut self, bwtype: &str, bandwidth: u32) {
136 unsafe {
137 ffi::gst_sdp_media_add_bandwidth(&mut self.0, bwtype.to_glib_none().0, bandwidth)
138 };
139 }
140
141 #[doc(alias = "gst_sdp_media_add_connection")]
142 pub fn add_connection(
143 &mut self,
144 nettype: &str,
145 addrtype: &str,
146 address: &str,
147 ttl: u32,
148 addr_number: u32,
149 ) {
150 unsafe {
151 ffi::gst_sdp_media_add_connection(
152 &mut self.0,
153 nettype.to_glib_none().0,
154 addrtype.to_glib_none().0,
155 address.to_glib_none().0,
156 ttl,
157 addr_number,
158 )
159 };
160 }
161
162 #[doc(alias = "gst_sdp_media_add_format")]
163 pub fn add_format(&mut self, format: &str) {
164 unsafe { ffi::gst_sdp_media_add_format(&mut self.0, format.to_glib_none().0) };
165 }
166
167 #[doc(alias = "gst_sdp_media_as_text")]
168 pub fn as_text(&self) -> Result<String, glib::error::BoolError> {
169 unsafe {
170 match from_glib_full(ffi::gst_sdp_media_as_text(&self.0)) {
171 Some(s) => Ok(s),
172 None => Err(glib::bool_error!(
173 "Failed to convert the contents of media to a text string"
174 )),
175 }
176 }
177 }
178
179 pub fn attributes(&self) -> AttributesIter {
180 AttributesIter::new(self)
181 }
182
183 pub fn formats(&self) -> FormatsIter {
184 FormatsIter::new(self)
185 }
186
187 pub fn bandwidths(&self) -> BandwidthsIter {
188 BandwidthsIter::new(self)
189 }
190
191 pub fn connections(&self) -> ConnectionsIter {
192 ConnectionsIter::new(self)
193 }
194
195 #[doc(alias = "gst_sdp_media_attributes_len")]
196 pub fn attributes_len(&self) -> u32 {
197 unsafe { ffi::gst_sdp_media_attributes_len(&self.0) }
198 }
199
200 #[doc(alias = "gst_sdp_media_attributes_to_caps")]
201 pub fn attributes_to_caps(&self, caps: &mut gst::CapsRef) -> Result<(), glib::BoolError> {
202 let result = unsafe { ffi::gst_sdp_media_attributes_to_caps(&self.0, caps.as_mut_ptr()) };
203 match result {
204 ffi::GST_SDP_OK => Ok(()),
205 _ => Err(glib::bool_error!("Failed to store attributes in caps")),
206 }
207 }
208
209 #[doc(alias = "gst_sdp_media_bandwidths_len")]
210 pub fn bandwidths_len(&self) -> u32 {
211 unsafe { ffi::gst_sdp_media_bandwidths_len(&self.0) }
212 }
213
214 #[doc(alias = "gst_sdp_media_connections_len")]
215 pub fn connections_len(&self) -> u32 {
216 unsafe { ffi::gst_sdp_media_connections_len(&self.0) }
217 }
218
219 #[doc(alias = "gst_sdp_media_formats_len")]
220 pub fn formats_len(&self) -> u32 {
221 unsafe { ffi::gst_sdp_media_formats_len(&self.0) }
222 }
223
224 #[doc(alias = "get_attribute")]
225 #[doc(alias = "gst_sdp_media_get_attribute")]
226 pub fn attribute(&self, idx: u32) -> Option<&SDPAttribute> {
227 if idx >= self.attributes_len() {
228 return None;
229 }
230
231 unsafe {
232 let ptr = ffi::gst_sdp_media_get_attribute(&self.0, idx);
233 if ptr.is_null() {
234 None
235 } else {
236 Some(&*(ptr as *mut SDPAttribute))
237 }
238 }
239 }
240
241 #[doc(alias = "get_attribute_val")]
242 #[doc(alias = "gst_sdp_media_get_attribute_val")]
243 pub fn attribute_val(&self, key: &str) -> Option<&str> {
244 unsafe {
245 let ptr = ffi::gst_sdp_media_get_attribute_val(&self.0, key.to_glib_none().0);
246 if ptr.is_null() {
247 None
248 } else {
249 CStr::from_ptr(ptr).to_str().ok()
250 }
251 }
252 }
253
254 #[doc(alias = "get_attribute_val_n")]
255 #[doc(alias = "gst_sdp_media_get_attribute_val_n")]
256 pub fn attribute_val_n(&self, key: &str, nth: u32) -> Option<&str> {
257 unsafe {
258 let ptr = ffi::gst_sdp_media_get_attribute_val_n(&self.0, key.to_glib_none().0, nth);
259 if ptr.is_null() {
260 None
261 } else {
262 CStr::from_ptr(ptr).to_str().ok()
263 }
264 }
265 }
266
267 #[doc(alias = "get_bandwidth")]
268 #[doc(alias = "gst_sdp_media_get_bandwidth")]
269 pub fn bandwidth(&self, idx: u32) -> Option<&SDPBandwidth> {
270 if idx >= self.bandwidths_len() {
271 return None;
272 }
273
274 unsafe {
275 let ptr = ffi::gst_sdp_media_get_bandwidth(&self.0, idx);
276 if ptr.is_null() {
277 None
278 } else {
279 Some(&*(ptr as *mut SDPBandwidth))
280 }
281 }
282 }
283
284 #[doc(alias = "get_caps_from_media")]
285 #[doc(alias = "gst_sdp_media_get_caps_from_media")]
286 pub fn caps_from_media(&self, pt: i32) -> Option<gst::Caps> {
287 unsafe { from_glib_full(ffi::gst_sdp_media_get_caps_from_media(&self.0, pt)) }
288 }
289
290 #[doc(alias = "get_connection")]
291 #[doc(alias = "gst_sdp_media_get_connection")]
292 pub fn connection(&self, idx: u32) -> Option<&SDPConnection> {
293 if idx >= self.connections_len() {
294 return None;
295 }
296
297 unsafe {
298 let ptr = ffi::gst_sdp_media_get_connection(&self.0, idx);
299 if ptr.is_null() {
300 None
301 } else {
302 Some(&*(ptr as *mut SDPConnection))
303 }
304 }
305 }
306
307 #[doc(alias = "get_format")]
308 #[doc(alias = "gst_sdp_media_get_format")]
309 pub fn format(&self, idx: u32) -> Option<&str> {
310 if idx >= self.formats_len() {
311 return None;
312 }
313
314 unsafe {
315 let ptr = ffi::gst_sdp_media_get_format(&self.0, idx);
316 if ptr.is_null() {
317 None
318 } else {
319 CStr::from_ptr(ptr).to_str().ok()
320 }
321 }
322 }
323
324 #[doc(alias = "get_information")]
325 #[doc(alias = "gst_sdp_media_get_information")]
326 pub fn information(&self) -> Option<&str> {
327 unsafe {
328 let ptr = ffi::gst_sdp_media_get_information(&self.0);
329 if ptr.is_null() {
330 None
331 } else {
332 CStr::from_ptr(ptr).to_str().ok()
333 }
334 }
335 }
336
337 #[doc(alias = "get_key")]
338 #[doc(alias = "gst_sdp_media_get_key")]
339 pub fn key(&self) -> Option<&SDPKey> {
340 unsafe {
341 let ptr = ffi::gst_sdp_media_get_key(&self.0);
342 if ptr.is_null() {
343 None
344 } else {
345 Some(&*(ptr as *mut SDPKey))
346 }
347 }
348 }
349
350 #[doc(alias = "get_media")]
351 #[doc(alias = "gst_sdp_media_get_media")]
352 pub fn media(&self) -> Option<&str> {
353 unsafe {
354 let ptr = ffi::gst_sdp_media_get_media(&self.0);
355 if ptr.is_null() {
356 None
357 } else {
358 CStr::from_ptr(ptr).to_str().ok()
359 }
360 }
361 }
362
363 #[doc(alias = "get_num_ports")]
364 #[doc(alias = "gst_sdp_media_get_num_ports")]
365 pub fn num_ports(&self) -> u32 {
366 unsafe { ffi::gst_sdp_media_get_num_ports(&self.0) }
367 }
368
369 #[doc(alias = "get_port")]
370 #[doc(alias = "gst_sdp_media_get_port")]
371 pub fn port(&self) -> u32 {
372 unsafe { ffi::gst_sdp_media_get_port(&self.0) }
373 }
374
375 #[doc(alias = "get_proto")]
376 #[doc(alias = "gst_sdp_media_get_proto")]
377 pub fn proto(&self) -> Option<&str> {
378 unsafe {
379 let ptr = ffi::gst_sdp_media_get_proto(&self.0);
380 if ptr.is_null() {
381 None
382 } else {
383 CStr::from_ptr(ptr).to_str().ok()
384 }
385 }
386 }
387
388 #[doc(alias = "gst_sdp_media_insert_attribute")]
389 pub fn insert_attribute(
390 &mut self,
391 idx: Option<u32>,
392 attr: SDPAttribute,
393 ) -> Result<(), glib::BoolError> {
394 if let Some(idx) = idx {
395 if idx >= self.attributes_len() {
396 return Err(glib::bool_error!("Failed to insert attribute"));
397 }
398 }
399
400 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
401 let mut attr = mem::ManuallyDrop::new(attr);
402 let result = unsafe { ffi::gst_sdp_media_insert_attribute(&mut self.0, idx, &mut attr.0) };
403 match result {
404 ffi::GST_SDP_OK => Ok(()),
405 _ => Err(glib::bool_error!("Failed to insert attribute")),
406 }
407 }
408
409 #[doc(alias = "gst_sdp_media_insert_bandwidth")]
410 pub fn insert_bandwidth(
411 &mut self,
412 idx: Option<u32>,
413 bw: SDPBandwidth,
414 ) -> Result<(), glib::BoolError> {
415 if let Some(idx) = idx {
416 if idx >= self.bandwidths_len() {
417 return Err(glib::bool_error!("Failed to insert bandwidth"));
418 }
419 }
420
421 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
422 let mut bw = mem::ManuallyDrop::new(bw);
423 let result = unsafe { ffi::gst_sdp_media_insert_bandwidth(&mut self.0, idx, &mut bw.0) };
424 match result {
425 ffi::GST_SDP_OK => Ok(()),
426 _ => Err(glib::bool_error!("Failed to insert attribute")),
427 }
428 }
429
430 #[doc(alias = "gst_sdp_media_insert_connection")]
431 pub fn insert_connection(
432 &mut self,
433 idx: Option<u32>,
434 conn: SDPConnection,
435 ) -> Result<(), glib::BoolError> {
436 if let Some(idx) = idx {
437 if idx >= self.connections_len() {
438 return Err(glib::bool_error!("Failed to insert connection"));
439 }
440 }
441
442 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
443 let mut conn = mem::ManuallyDrop::new(conn);
444 let result = unsafe { ffi::gst_sdp_media_insert_connection(&mut self.0, idx, &mut conn.0) };
445 match result {
446 ffi::GST_SDP_OK => Ok(()),
447 _ => Err(glib::bool_error!("Failed to insert connection")),
448 }
449 }
450
451 #[doc(alias = "gst_sdp_media_insert_format")]
452 pub fn insert_format(&mut self, idx: Option<u32>, format: &str) -> Result<(), glib::BoolError> {
453 if let Some(idx) = idx {
454 if idx >= self.formats_len() {
455 return Err(glib::bool_error!("Failed to insert format"));
456 }
457 }
458
459 let idx = idx.map(|idx| idx as i32).unwrap_or(-1);
460 let result =
461 unsafe { ffi::gst_sdp_media_insert_format(&mut self.0, idx, format.to_glib_none().0) };
462 match result {
463 ffi::GST_SDP_OK => Ok(()),
464 _ => Err(glib::bool_error!("Failed to insert format")),
465 }
466 }
467
468 #[doc(alias = "gst_sdp_media_remove_attribute")]
469 pub fn remove_attribute(&mut self, idx: u32) -> Result<(), glib::BoolError> {
470 if idx >= self.attributes_len() {
471 return Err(glib::bool_error!("Failed to remove attribute"));
472 }
473
474 let result = unsafe { ffi::gst_sdp_media_remove_attribute(&mut self.0, idx) };
475 match result {
476 ffi::GST_SDP_OK => Ok(()),
477 _ => Err(glib::bool_error!("Failed to remove attribute")),
478 }
479 }
480
481 #[doc(alias = "gst_sdp_media_remove_bandwidth")]
482 pub fn remove_bandwidth(&mut self, idx: u32) -> Result<(), glib::BoolError> {
483 if idx >= self.bandwidths_len() {
484 return Err(glib::bool_error!("Failed to remove bandwidth"));
485 }
486
487 let result = unsafe { ffi::gst_sdp_media_remove_bandwidth(&mut self.0, idx) };
488 match result {
489 ffi::GST_SDP_OK => Ok(()),
490 _ => Err(glib::bool_error!("Failed to remove bandwidth")),
491 }
492 }
493
494 #[doc(alias = "gst_sdp_media_remove_connection")]
495 pub fn remove_connection(&mut self, idx: u32) -> Result<(), glib::BoolError> {
496 if idx >= self.connections_len() {
497 return Err(glib::bool_error!("Failed to remove connection"));
498 }
499
500 let result = unsafe { ffi::gst_sdp_media_remove_connection(&mut self.0, idx) };
501 match result {
502 ffi::GST_SDP_OK => Ok(()),
503 _ => Err(glib::bool_error!("Failed to remove connection")),
504 }
505 }
506
507 #[doc(alias = "gst_sdp_media_remove_format")]
508 pub fn remove_format(&mut self, idx: u32) -> Result<(), glib::BoolError> {
509 if idx >= self.formats_len() {
510 return Err(glib::bool_error!("Failed to remove format"));
511 }
512
513 let result = unsafe { ffi::gst_sdp_media_remove_format(&mut self.0, idx) };
514 match result {
515 ffi::GST_SDP_OK => Ok(()),
516 _ => Err(glib::bool_error!("Failed to remove format")),
517 }
518 }
519
520 #[doc(alias = "gst_sdp_media_replace_attribute")]
521 pub fn replace_attribute(
522 &mut self,
523 idx: u32,
524 attr: SDPAttribute,
525 ) -> Result<(), glib::BoolError> {
526 if idx >= self.attributes_len() {
527 return Err(glib::bool_error!("Failed to replace attribute"));
528 }
529
530 let mut attr = mem::ManuallyDrop::new(attr);
531 let result = unsafe { ffi::gst_sdp_media_replace_attribute(&mut self.0, idx, &mut attr.0) };
532 match result {
533 ffi::GST_SDP_OK => Ok(()),
534 _ => Err(glib::bool_error!("Failed to replace attribute")),
535 }
536 }
537
538 #[doc(alias = "gst_sdp_media_replace_bandwidth")]
539 pub fn replace_bandwidth(&mut self, idx: u32, bw: SDPBandwidth) -> Result<(), glib::BoolError> {
540 if idx >= self.bandwidths_len() {
541 return Err(glib::bool_error!("Failed to replace bandwidth"));
542 }
543
544 let mut bw = mem::ManuallyDrop::new(bw);
545 let result = unsafe { ffi::gst_sdp_media_replace_bandwidth(&mut self.0, idx, &mut bw.0) };
546 match result {
547 ffi::GST_SDP_OK => Ok(()),
548 _ => Err(glib::bool_error!("Failed to replace bandwidth")),
549 }
550 }
551
552 #[doc(alias = "gst_sdp_media_replace_connection")]
553 pub fn replace_connection(
554 &mut self,
555 idx: u32,
556 conn: SDPConnection,
557 ) -> Result<(), glib::BoolError> {
558 if idx >= self.connections_len() {
559 return Err(glib::bool_error!("Failed to replace connection"));
560 }
561
562 let mut conn = mem::ManuallyDrop::new(conn);
563 let result =
564 unsafe { ffi::gst_sdp_media_replace_connection(&mut self.0, idx, &mut conn.0) };
565 match result {
566 ffi::GST_SDP_OK => Ok(()),
567 _ => Err(glib::bool_error!("Failed to replace connection")),
568 }
569 }
570
571 #[doc(alias = "gst_sdp_media_replace_format")]
572 pub fn replace_format(&mut self, idx: u32, format: &str) -> Result<(), glib::BoolError> {
573 if idx >= self.formats_len() {
574 return Err(glib::bool_error!("Failed to replace format"));
575 }
576
577 let result =
578 unsafe { ffi::gst_sdp_media_replace_format(&mut self.0, idx, format.to_glib_none().0) };
579 match result {
580 ffi::GST_SDP_OK => Ok(()),
581 _ => Err(glib::bool_error!("Failed to replace format")),
582 }
583 }
584
585 #[doc(alias = "gst_sdp_media_set_information")]
586 pub fn set_information(&mut self, information: &str) {
587 unsafe { ffi::gst_sdp_media_set_information(&mut self.0, information.to_glib_none().0) };
588 }
589
590 #[doc(alias = "gst_sdp_media_set_key")]
591 pub fn set_key(&mut self, type_: &str, data: &str) {
592 unsafe {
593 ffi::gst_sdp_media_set_key(&mut self.0, type_.to_glib_none().0, data.to_glib_none().0)
594 };
595 }
596
597 #[doc(alias = "gst_sdp_media_set_media")]
598 pub fn set_media(&mut self, med: &str) {
599 unsafe { ffi::gst_sdp_media_set_media(&mut self.0, med.to_glib_none().0) };
600 }
601
602 #[doc(alias = "gst_sdp_media_set_port_info")]
603 pub fn set_port_info(&mut self, port: u32, num_ports: u32) {
604 unsafe { ffi::gst_sdp_media_set_port_info(&mut self.0, port, num_ports) };
605 }
606
607 #[doc(alias = "gst_sdp_media_set_proto")]
608 pub fn set_proto(&mut self, proto: &str) {
609 unsafe { ffi::gst_sdp_media_set_proto(&mut self.0, proto.to_glib_none().0) };
610 }
611
612 #[doc(alias = "gst_sdp_media_set_media_from_caps")]
613 pub fn set_media_from_caps(
614 caps: &gst::CapsRef,
615 media: &mut SDPMedia,
616 ) -> Result<(), glib::BoolError> {
617 skip_assert_initialized!();
618 let result = unsafe {
619 ffi::gst_sdp_media_set_media_from_caps(caps.as_ptr(), media.to_glib_none_mut().0)
620 };
621 match result {
622 ffi::GST_SDP_OK => Ok(()),
623 _ => Err(glib::bool_error!("Failed to set media from caps")),
624 }
625 }
626}
627
628impl Borrow<SDPMediaRef> for SDPMedia {
629 fn borrow(&self) -> &SDPMediaRef {
630 self
631 }
632}
633
634impl BorrowMut<SDPMediaRef> for SDPMedia {
635 fn borrow_mut(&mut self) -> &mut SDPMediaRef {
636 &mut *self
637 }
638}
639
640impl ToOwned for SDPMediaRef {
641 type Owned = SDPMedia;
642
643 fn to_owned(&self) -> SDPMedia {
644 unsafe {
645 let mut ptr = ptr::null_mut();
646 ffi::gst_sdp_media_copy(&self.0, &mut ptr);
647 from_glib_full(ptr)
648 }
649 }
650}
651
652macro_rules! define_iter(
653 ($name:ident, $typ:ty, $get_item:expr, $get_len:expr) => {
654 #[must_use = "iterators are lazy and do nothing unless consumed"]
655 #[derive(Debug)]
656 pub struct $name<'a> {
657 media: &'a SDPMediaRef,
658 idx: usize,
659 len: usize,
660 }
661
662 impl<'a> $name<'a> {
663 #[allow(clippy::redundant_closure_call)]
664 fn new(media: &'a SDPMediaRef) -> $name<'a> {
665 skip_assert_initialized!();
666 let len = $get_len(media);
667
668 $name {
669 media,
670 idx: 0,
671 len: len as usize,
672 }
673 }
674 }
675
676 #[allow(clippy::redundant_closure_call)]
677 impl<'a> Iterator for $name<'a> {
678 type Item = $typ;
679
680 fn next(&mut self) -> Option<Self::Item> {
681 if self.idx >= self.len {
682 return None;
683 }
684
685 let item = $get_item(self.media, self.idx as u32).unwrap();
686 self.idx += 1;
687 Some(item)
688 }
689
690 fn size_hint(&self) -> (usize, Option<usize>) {
691 let remaining = self.len - self.idx;
692
693 (remaining, Some(remaining))
694 }
695
696
697 fn count(self) -> usize {
698 self.len - self.idx
699 }
700
701 fn nth(&mut self, n: usize) -> Option<Self::Item> {
702 let (end, overflow) = self.idx.overflowing_add(n);
703 if end >= self.len || overflow {
704 self.idx = self.len;
705 None
706 } else {
707 self.idx = end + 1;
708 Some($get_item(self.media, end as u32).unwrap())
709 }
710 }
711
712 fn last(self) -> Option<Self::Item> {
713 if self.idx == self.len {
714 None
715 } else {
716 Some($get_item(self.media, self.len as u32 - 1).unwrap())
717 }
718 }
719 }
720
721 #[allow(clippy::redundant_closure_call)]
722 impl<'a> DoubleEndedIterator for $name<'a> {
723 fn next_back(&mut self) -> Option<Self::Item> {
724 if self.idx == self.len {
725 return None;
726 }
727
728 self.len -= 1;
729
730 Some($get_item(self.media, self.len as u32).unwrap())
731 }
732
733 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
734 let (end, overflow) = self.len.overflowing_sub(n);
735 if end <= self.idx || overflow {
736 self.idx = self.len;
737 None
738 } else {
739 self.len = end - 1;
740 Some($get_item(self.media, self.len as u32).unwrap())
741 }
742 }
743 }
744
745 impl<'a> ExactSizeIterator for $name<'a> {}
746
747 impl<'a> std::iter::FusedIterator for $name<'a> {}
748 }
749);
750
751define_iter!(
752 BandwidthsIter,
753 &'a SDPBandwidth,
754 |media: &'a SDPMediaRef, idx| media.bandwidth(idx),
755 |media: &SDPMediaRef| media.bandwidths_len()
756);
757define_iter!(
758 FormatsIter,
759 &'a str,
760 |media: &'a SDPMediaRef, idx| media.format(idx),
761 |media: &SDPMediaRef| media.formats_len()
762);
763define_iter!(
764 ConnectionsIter,
765 &'a SDPConnection,
766 |media: &'a SDPMediaRef, idx| media.connection(idx),
767 |media: &SDPMediaRef| media.connections_len()
768);
769define_iter!(
770 AttributesIter,
771 &'a SDPAttribute,
772 |media: &'a SDPMediaRef, idx| media.attribute(idx),
773 |media: &SDPMediaRef| media.attributes_len()
774);
775
776#[cfg(test)]
777mod tests {
778 use super::*;
779
780 fn init() {
781 gst::init().unwrap();
782 }
783
784 #[test]
785 fn debug_impl() {
786 init();
787
788 let sdp = SDPMedia::new();
789 assert!(!format!("{sdp:?}").is_empty());
790 }
791}