diff --git a/gstreamer-sdp/src/lib.rs b/gstreamer-sdp/src/lib.rs index 995186a10..a77062494 100644 --- a/gstreamer-sdp/src/lib.rs +++ b/gstreamer-sdp/src/lib.rs @@ -56,10 +56,10 @@ mod sdp_connection; pub use sdp_connection::*; mod sdp_key; pub use sdp_key::*; -mod sdp_media; +pub mod sdp_media; pub use sdp_media::{SDPMedia, SDPMediaRef}; -mod sdp_message; -pub use sdp_message::*; +pub mod sdp_message; +pub use sdp_message::{SDPMessage, SDPMessageRef}; mod sdp_origin; pub use sdp_origin::*; mod sdp_time; diff --git a/gstreamer-sdp/src/sdp_message.rs b/gstreamer-sdp/src/sdp_message.rs index 7b6792a39..8af8b1d85 100644 --- a/gstreamer-sdp/src/sdp_message.rs +++ b/gstreamer-sdp/src/sdp_message.rs @@ -766,8 +766,141 @@ impl SDPMessageRef { )) } } + + pub fn attributes(&self) -> AttributesIter { + AttributesIter::new(self) + } + + pub fn bandwidths(&self) -> BandwidthsIter { + BandwidthsIter::new(self) + } + + pub fn emails(&self) -> EmailsIter { + EmailsIter::new(self) + } + + pub fn medias(&self) -> MediasIter { + MediasIter::new(self) + } + + pub fn phones(&self) -> PhonesIter { + PhonesIter::new(self) + } + + pub fn times(&self) -> TimesIter { + TimesIter::new(self) + } + + pub fn zones(&self) -> ZonesIter { + ZonesIter::new(self) + } } +macro_rules! define_iter( + ($name:ident, $typ:ty, $get_item:expr, $get_len:expr) => { + #[derive(Debug)] + pub struct $name<'a> { + message: &'a SDPMessageRef, + idx: u32, + len: u32, + } + + impl<'a> $name<'a> { + fn new(message: &'a SDPMessageRef) -> $name<'a> { + skip_assert_initialized!(); + let len = $get_len(message); + + $name { + message, + idx: 0, + len, + } + } + } + + impl<'a> Iterator for $name<'a> { + type Item = $typ; + + fn next(&mut self) -> Option { + if self.idx >= self.len { + return None; + } + + let item = $get_item(self.message, self.idx)?; + self.idx += 1; + Some(item) + } + + fn size_hint(&self) -> (usize, Option) { + if self.idx == self.len { + return (0, Some(0)) + } + + let remaining = (self.len - self.idx) as usize; + + (remaining, Some(remaining)) + } + } + + impl<'a> DoubleEndedIterator for $name<'a> { + fn next_back(&mut self) -> Option { + if self.idx == self.len { + return None; + } + + self.len -= 1; + + $get_item(self.message, self.len) + } + } + + impl<'a> ExactSizeIterator for $name<'a> {} + } +); + +define_iter!( + AttributesIter, + &'a SDPAttribute, + |message: &'a SDPMessageRef, idx| message.get_attribute(idx), + |message: &SDPMessageRef| message.attributes_len() +); +define_iter!( + BandwidthsIter, + &'a SDPBandwidth, + |message: &'a SDPMessageRef, idx| message.get_bandwidth(idx), + |message: &SDPMessageRef| message.bandwidths_len() +); +define_iter!( + EmailsIter, + &'a str, + |message: &'a SDPMessageRef, idx| message.get_email(idx), + |message: &SDPMessageRef| message.emails_len() +); +define_iter!( + MediasIter, + &'a SDPMediaRef, + |message: &'a SDPMessageRef, idx| message.get_media(idx), + |message: &SDPMessageRef| message.medias_len() +); +define_iter!( + PhonesIter, + &'a str, + |message: &'a SDPMessageRef, idx| message.get_phone(idx), + |message: &SDPMessageRef| message.phones_len() +); +define_iter!( + TimesIter, + &'a SDPTime, + |message: &'a SDPMessageRef, idx| message.get_time(idx), + |message: &SDPMessageRef| message.times_len() +); +define_iter!( + ZonesIter, + &'a SDPZone, + |message: &'a SDPMessageRef, idx| message.get_zone(idx), + |message: &SDPMessageRef| message.zones_len() +); + #[cfg(test)] mod tests { use super::*;