From d4430ecc6ab9efa3195f2c2b3a5d6239ef07ba32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 20 May 2022 16:58:46 +0300 Subject: [PATCH] Implement more iterator functions / traits in custom iterators for efficiency reasons --- gstreamer-audio/src/audio_format.rs | 45 +++- .../src/discoverer_stream_info.rs | 2 + gstreamer-sdp/src/sdp_media.rs | 53 ++++- gstreamer-sdp/src/sdp_message.rs | 109 +++++++-- gstreamer-video/src/video_format.rs | 37 +++ gstreamer-video/src/video_meta.rs | 24 +- .../src/video_overlay_composition.rs | 54 ++++- gstreamer/src/buffer.rs | 66 +++++- gstreamer/src/bufferlist.rs | 51 +++- gstreamer/src/caps.rs | 58 ++++- gstreamer/src/caps_features.rs | 82 +++++-- gstreamer/src/iterator.rs | 2 + gstreamer/src/stream_collection.rs | 54 ++++- gstreamer/src/structure.rs | 69 +++--- gstreamer/src/tags.rs | 219 ++++++++++++++---- 15 files changed, 739 insertions(+), 186 deletions(-) diff --git a/gstreamer-audio/src/audio_format.rs b/gstreamer-audio/src/audio_format.rs index 5212814f4..8566418fc 100644 --- a/gstreamer-audio/src/audio_format.rs +++ b/gstreamer-audio/src/audio_format.rs @@ -255,25 +255,58 @@ impl Iterator for AudioFormatIterator { } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.len { - return (0, Some(0)); - } - - let remaining = (self.len - self.idx) as usize; + let remaining = self.len - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.len - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.len || overflow { + self.idx = self.len; + None + } else { + self.idx = end + 1; + Some(AUDIO_FORMATS_ALL[end]) + } + } + + fn last(self) -> Option { + if self.idx == self.len { + None + } else { + Some(AUDIO_FORMATS_ALL[self.len - 1]) + } + } } impl ExactSizeIterator for AudioFormatIterator {} +impl std::iter::FusedIterator for AudioFormatIterator {} + impl DoubleEndedIterator for AudioFormatIterator { fn next_back(&mut self) -> Option { if self.idx >= self.len { None } else { - let fmt = AUDIO_FORMATS_ALL[self.len - 1]; self.len -= 1; + let fmt = AUDIO_FORMATS_ALL[self.len]; + Some(fmt) + } + } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.len.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.len; + None + } else { + self.len = end - 1; + let fmt = AUDIO_FORMATS_ALL[self.len]; Some(fmt) } } diff --git a/gstreamer-pbutils/src/discoverer_stream_info.rs b/gstreamer-pbutils/src/discoverer_stream_info.rs index 339d629d4..b3d697b8a 100644 --- a/gstreamer-pbutils/src/discoverer_stream_info.rs +++ b/gstreamer-pbutils/src/discoverer_stream_info.rs @@ -44,3 +44,5 @@ impl DiscovererStreamInfo { } } } + +impl std::iter::FusedIterator for Iter {} diff --git a/gstreamer-sdp/src/sdp_media.rs b/gstreamer-sdp/src/sdp_media.rs index 04a5f4449..61bbf24a4 100644 --- a/gstreamer-sdp/src/sdp_media.rs +++ b/gstreamer-sdp/src/sdp_media.rs @@ -656,8 +656,8 @@ macro_rules! define_iter( #[derive(Debug)] pub struct $name<'a> { media: &'a SDPMediaRef, - idx: u32, - len: u32, + idx: usize, + len: usize, } impl<'a> $name<'a> { @@ -668,7 +668,7 @@ macro_rules! define_iter( $name { media, idx: 0, - len, + len: len as usize, } } } @@ -681,20 +681,40 @@ macro_rules! define_iter( return None; } - let item = $get_item(self.media, self.idx)?; + let item = $get_item(self.media, self.idx as u32).unwrap(); 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; + let remaining = self.len - self.idx; (remaining, Some(remaining)) } + + + fn count(self) -> usize { + self.len - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.len || overflow { + self.idx = self.len; + None + } else { + self.idx = end + 1; + Some($get_item(self.media, end as u32).unwrap()) + } + } + + fn last(self) -> Option { + if self.idx == self.len { + None + } else { + Some($get_item(self.media, self.len as u32 - 1).unwrap()) + } + } } impl<'a> DoubleEndedIterator for $name<'a> { @@ -705,11 +725,24 @@ macro_rules! define_iter( self.len -= 1; - $get_item(self.media, self.len) + Some($get_item(self.media, self.len as u32).unwrap()) + } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.len.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.len; + None + } else { + self.len = end - 1; + Some($get_item(self.media, self.len as u32).unwrap()) + } } } impl<'a> ExactSizeIterator for $name<'a> {} + + impl<'a> std::iter::FusedIterator for $name<'a> {} } ); diff --git a/gstreamer-sdp/src/sdp_message.rs b/gstreamer-sdp/src/sdp_message.rs index 2eca449b6..aa12d36f0 100644 --- a/gstreamer-sdp/src/sdp_message.rs +++ b/gstreamer-sdp/src/sdp_message.rs @@ -1009,8 +1009,8 @@ macro_rules! define_iter( #[derive(Debug)] pub struct $name<'a> { message: &'a SDPMessageRef, - idx: u32, - len: u32, + idx: usize, + len: usize, } impl<'a> $name<'a> { @@ -1021,7 +1021,7 @@ macro_rules! define_iter( $name { message, idx: 0, - len, + len: len as usize, } } } @@ -1034,20 +1034,39 @@ macro_rules! define_iter( return None; } - let item = $get_item(self.message, self.idx)?; + let item = $get_item(self.message, self.idx as u32).unwrap(); 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; + let remaining = self.len - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.len - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.len || overflow { + self.idx = self.len; + None + } else { + self.idx = end + 1; + Some($get_item(self.message, end as u32).unwrap()) + } + } + + fn last(self) -> Option { + if self.idx == self.len { + None + } else { + Some($get_item(self.message, self.len as u32 - 1).unwrap()) + } + } } impl<'a> DoubleEndedIterator for $name<'a> { @@ -1058,11 +1077,23 @@ macro_rules! define_iter( self.len -= 1; - $get_item(self.message, self.len) + Some($get_item(self.message, self.len as u32).unwrap()) + } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.len.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.len; + None + } else { + self.len = end - 1; + Some($get_item(self.message, self.len as u32).unwrap()) + } } } impl<'a> ExactSizeIterator for $name<'a> {} + impl<'a> std::iter::FusedIterator for $name<'a> {} } ); @@ -1071,8 +1102,8 @@ macro_rules! define_iter_mut( #[derive(Debug)] pub struct $name<'a> { message: &'a mut SDPMessageRef, - idx: u32, - len: u32, + idx: usize, + len: usize, } impl<'a> $name<'a> { @@ -1083,7 +1114,7 @@ macro_rules! define_iter_mut( $name { message, idx: 0, - len, + len: len as usize, } } } @@ -1108,20 +1139,43 @@ macro_rules! define_iter_mut( return None; } - let item = $get_item(message, self.idx)?; + let item = $get_item(message, self.idx as u32).unwrap(); 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; + let remaining = self.len - self.idx; (remaining, Some(remaining)) } + + + fn count(self) -> usize { + self.len - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let message = unsafe { + &mut *(self.message as *mut SDPMessageRef) + }; + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.len || overflow { + self.idx = self.len; + None + } else { + self.idx = end + 1; + Some($get_item(message, end as u32).unwrap()) + } + } + + fn last(self) -> Option { + if self.idx == self.len { + None + } else { + Some($get_item(self.message, self.len as u32 - 1).unwrap()) + } + } } impl<'a> DoubleEndedIterator for $name<'a> { @@ -1134,12 +1188,27 @@ macro_rules! define_iter_mut( } self.len -= 1; + Some($get_item(message, self.len as u32).unwrap()) + } - $get_item(message, self.len) + + fn nth_back(&mut self, n: usize) -> Option { + let message = unsafe { + &mut *(self.message as *mut SDPMessageRef) + }; + let (end, overflow) = self.len.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.len; + None + } else { + self.len = end - 1; + Some($get_item(message, self.len as u32).unwrap()) + } } } impl<'a> ExactSizeIterator for $name<'a> {} + impl<'a> std::iter::FusedIterator for $name<'a> {} } ); diff --git a/gstreamer-video/src/video_format.rs b/gstreamer-video/src/video_format.rs index def19095e..d0eb1f158 100644 --- a/gstreamer-video/src/video_format.rs +++ b/gstreamer-video/src/video_format.rs @@ -354,10 +354,35 @@ impl Iterator for VideoFormatIterator { (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.len - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.len || overflow { + self.idx = self.len; + None + } else { + self.idx = end + 1; + Some(VIDEO_FORMATS_ALL[end]) + } + } + + fn last(self) -> Option { + if self.idx == self.len { + None + } else { + Some(VIDEO_FORMATS_ALL[self.len - 1]) + } + } } impl ExactSizeIterator for VideoFormatIterator {} +impl std::iter::FusedIterator for VideoFormatIterator {} + impl DoubleEndedIterator for VideoFormatIterator { fn next_back(&mut self) -> Option { if self.idx >= self.len { @@ -368,6 +393,18 @@ impl DoubleEndedIterator for VideoFormatIterator { Some(fmt) } } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.len.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.len; + None + } else { + self.len = end - 1; + let fmt = VIDEO_FORMATS_ALL[self.len]; + Some(fmt) + } + } } pub trait VideoFormatIteratorExt { fn into_video_caps(self) -> Option>; diff --git a/gstreamer-video/src/video_meta.rs b/gstreamer-video/src/video_meta.rs index 1e11a6bcf..a8b136b07 100644 --- a/gstreamer-video/src/video_meta.rs +++ b/gstreamer-video/src/video_meta.rs @@ -361,7 +361,7 @@ impl VideoRegionOfInterestMeta { pub fn params(&self) -> ParamsIter { ParamsIter { _meta: self, - list: self.0.params, + list: ptr::NonNull::new(self.0.params), } } @@ -395,29 +395,29 @@ impl VideoRegionOfInterestMeta { pub struct ParamsIter<'a> { _meta: &'a VideoRegionOfInterestMeta, - list: *const glib::ffi::GList, + list: Option>, } impl<'a> Iterator for ParamsIter<'a> { type Item = &'a gst::StructureRef; fn next(&mut self) -> Option<&'a gst::StructureRef> { - if self.list.is_null() { - return None; - } + match self.list { + None => None, + Some(list) => unsafe { + self.list = ptr::NonNull::new(list.as_ref().next); + let data = list.as_ref().data; - unsafe { - let data = (*self.list).data; - assert!(!data.is_null()); - self.list = (*self.list).next; + let s = gst::StructureRef::from_glib_borrow(data as *const gst::ffi::GstStructure); - let s = gst::StructureRef::from_glib_borrow(data as *const gst::ffi::GstStructure); - - Some(s) + Some(s) + }, } } } +impl<'a> std::iter::FusedIterator for ParamsIter<'a> {} + unsafe impl MetaAPI for VideoRegionOfInterestMeta { type GstType = ffi::GstVideoRegionOfInterestMeta; diff --git a/gstreamer-video/src/video_overlay_composition.rs b/gstreamer-video/src/video_overlay_composition.rs index 53be581fb..308a7b4a6 100644 --- a/gstreamer-video/src/video_overlay_composition.rs +++ b/gstreamer-video/src/video_overlay_composition.rs @@ -328,7 +328,7 @@ impl VideoOverlayCompositionRef { Iter { composition: self, idx: 0, - len: self.n_rectangles(), + len: self.n_rectangles() as usize, } } } @@ -390,33 +390,52 @@ impl<'a> std::iter::FromIterator<&'a VideoOverlayRectangle> for VideoOverlayComp pub struct Iter<'a> { composition: &'a VideoOverlayCompositionRef, - idx: u32, - len: u32, + idx: usize, + len: usize, } impl<'a> Iterator for Iter<'a> { type Item = VideoOverlayRectangle; fn next(&mut self) -> Option { - if self.idx == self.len { + if self.idx >= self.len { return None; } - let rect = self.composition.rectangle(self.idx).unwrap(); + let rect = self.composition.rectangle(self.idx as u32).unwrap(); self.idx += 1; Some(rect) } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.len { - return (0, Some(0)); - } - - let remaining = (self.len - self.idx) as usize; + let remaining = self.len - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.len - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.len || overflow { + self.idx = self.len; + None + } else { + self.idx = end + 1; + Some(self.composition.rectangle(end as u32).unwrap()) + } + } + + fn last(self) -> Option { + if self.idx == self.len { + None + } else { + Some(self.composition.rectangle(self.len as u32 - 1).unwrap()) + } + } } impl<'a> DoubleEndedIterator for Iter<'a> { @@ -427,10 +446,21 @@ impl<'a> DoubleEndedIterator for Iter<'a> { self.len -= 1; - let rect = self.composition.rectangle(self.len).unwrap(); + Some(self.composition.rectangle(self.len as u32).unwrap()) + } - Some(rect) + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.len.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.len; + None + } else { + self.len = end - 1; + Some(self.composition.rectangle(self.len as u32).unwrap()) + } } } impl<'a> ExactSizeIterator for Iter<'a> {} + +impl<'a> std::iter::FusedIterator for Iter<'a> {} diff --git a/gstreamer/src/buffer.rs b/gstreamer/src/buffer.rs index 96de2daa0..4c1746327 100644 --- a/gstreamer/src/buffer.rs +++ b/gstreamer/src/buffer.rs @@ -816,6 +816,8 @@ macro_rules! define_meta_iter( } } } + + impl<'a, T: MetaAPI> std::iter::FusedIterator for $name<'a, T> { } } ); @@ -838,8 +840,8 @@ macro_rules! define_iter( ($name:ident, $typ:ty, $mtyp:ty, $get_item:expr) => { pub struct $name<'a> { buffer: $typ, - idx: u32, - n_memory: u32, + idx: usize, + n_memory: usize, } impl<'a> fmt::Debug for $name<'a> { @@ -861,7 +863,7 @@ macro_rules! define_iter( $name { buffer, idx: 0, - n_memory, + n_memory: n_memory as usize, } } } @@ -876,21 +878,46 @@ macro_rules! define_iter( #[allow(unused_unsafe)] unsafe { - let item = $get_item(self.buffer, self.idx)?; + let item = $get_item(self.buffer, self.idx as u32).unwrap(); self.idx += 1; Some(item) } } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.n_memory { - return (0, Some(0)); - } - - let remaining = (self.n_memory - self.idx) as usize; + let remaining = self.n_memory - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.n_memory - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.n_memory || overflow { + self.idx = self.n_memory; + None + } else { + #[allow(unused_unsafe)] + unsafe { + self.idx = end + 1; + Some($get_item(self.buffer, end as u32).unwrap()) + } + } + } + + fn last(self) -> Option { + if self.idx == self.n_memory { + None + } else { + #[allow(unused_unsafe)] + unsafe { + Some($get_item(self.buffer, self.n_memory as u32 - 1).unwrap()) + } + } + } } impl<'a> DoubleEndedIterator for $name<'a> { @@ -899,16 +926,31 @@ macro_rules! define_iter( return None; } - self.n_memory -= 1; - #[allow(unused_unsafe)] unsafe { - $get_item(self.buffer, self.n_memory) + self.n_memory -= 1; + Some($get_item(self.buffer, self.n_memory as u32).unwrap()) + } + } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.n_memory.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.n_memory; + None + } else { + #[allow(unused_unsafe)] + unsafe { + self.n_memory = end - 1; + Some($get_item(self.buffer, self.n_memory as u32).unwrap()) + } } } } impl<'a> ExactSizeIterator for $name<'a> {} + + impl<'a> std::iter::FusedIterator for $name<'a> {} } ); diff --git a/gstreamer/src/bufferlist.rs b/gstreamer/src/bufferlist.rs index d3fe8f041..c7938a476 100644 --- a/gstreamer/src/bufferlist.rs +++ b/gstreamer/src/bufferlist.rs @@ -215,8 +215,8 @@ macro_rules! define_iter( #[derive(Debug)] pub struct $name<'a> { list: &'a BufferListRef, - idx: u32, - size: u32, + idx: usize, + size: usize, } impl<'a> $name<'a> { @@ -225,7 +225,7 @@ macro_rules! define_iter( $name { list, idx: 0, - size: list.len() as u32, + size: list.len() as usize, } } } @@ -238,21 +238,40 @@ macro_rules! define_iter( return None; } - let item = $get_item(self.list, self.idx)?; + let item = $get_item(self.list, self.idx as u32).unwrap(); self.idx += 1; Some(item) } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.size { - return (0, Some(0)); - } - - let remaining = (self.size - self.idx) as usize; + let remaining = self.size - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.size - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.size || overflow { + self.idx = self.size; + None + } else { + self.idx = end + 1; + Some($get_item(self.list, end as u32).unwrap()) + } + } + + fn last(self) -> Option { + if self.idx == self.size { + None + } else { + Some($get_item(self.list, self.size as u32 - 1).unwrap()) + } + } } impl<'a> DoubleEndedIterator for $name<'a> { @@ -262,11 +281,23 @@ macro_rules! define_iter( } self.size -= 1; - $get_item(self.list, self.size) + Some($get_item(self.list, self.size as u32).unwrap()) + } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.size.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.size; + None + } else { + self.size = end - 1; + Some($get_item(self.list, self.size as u32).unwrap()) + } } } impl<'a> ExactSizeIterator for $name<'a> {} + impl<'a> std::iter::FusedIterator for $name<'a> {} } ); diff --git a/gstreamer/src/caps.rs b/gstreamer/src/caps.rs index 79f9f6e7d..c732ea3ab 100644 --- a/gstreamer/src/caps.rs +++ b/gstreamer/src/caps.rs @@ -597,8 +597,8 @@ macro_rules! define_iter( #[derive(Debug)] pub struct $name<'a> { caps: $typ, - idx: u32, - n_structures: u32, + idx: usize, + n_structures: usize, } impl<'a> $name<'a> { @@ -609,7 +609,7 @@ macro_rules! define_iter( $name { caps, idx: 0, - n_structures, + n_structures: n_structures as usize, } } } @@ -623,21 +623,44 @@ macro_rules! define_iter( } unsafe { - let item = $get_item(self.caps, self.idx)?; + let item = $get_item(self.caps, self.idx as u32).unwrap(); self.idx += 1; Some(item) } } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.n_structures { - return (0, Some(0)); - } - - let remaining = (self.n_structures - self.idx) as usize; + let remaining = self.n_structures - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.n_structures - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.n_structures || overflow { + self.idx = self.n_structures; + None + } else { + unsafe { + self.idx = end + 1; + Some($get_item(self.caps, end as u32).unwrap()) + } + } + } + + fn last(self) -> Option { + if self.idx == self.n_structures { + None + } else { + unsafe { + Some($get_item(self.caps, self.n_structures as u32 - 1).unwrap()) + } + } + } } impl<'a> DoubleEndedIterator for $name<'a> { @@ -649,12 +672,27 @@ macro_rules! define_iter( self.n_structures -= 1; unsafe { - $get_item(self.caps, self.n_structures) + Some($get_item(self.caps, self.n_structures as u32).unwrap()) + } + } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.n_structures.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.n_structures; + None + } else { + self.n_structures = end - 1; + unsafe { + Some($get_item(self.caps, self.n_structures as u32).unwrap()) + } } } } impl<'a> ExactSizeIterator for $name<'a> {} + + impl<'a> std::iter::FusedIterator for $name<'a> {} } ); diff --git a/gstreamer/src/caps_features.rs b/gstreamer/src/caps_features.rs index af651a682..56b2114f7 100644 --- a/gstreamer/src/caps_features.rs +++ b/gstreamer/src/caps_features.rs @@ -479,8 +479,8 @@ impl glib::value::ToValueOptional for CapsFeaturesRef { #[derive(Debug)] pub struct Iter<'a> { caps_features: &'a CapsFeaturesRef, - idx: u32, - n_features: u32, + idx: usize, + n_features: usize, } impl<'a> Iter<'a> { @@ -491,7 +491,7 @@ impl<'a> Iter<'a> { Iter { caps_features, idx: 0, - n_features, + n_features: n_features as usize, } } } @@ -505,10 +505,9 @@ impl<'a> Iterator for Iter<'a> { } unsafe { - let feature = ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.idx); - if feature.is_null() { - return None; - } + let feature = + ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.idx as u32); + assert!(!feature.is_null()); self.idx += 1; @@ -517,14 +516,46 @@ impl<'a> Iterator for Iter<'a> { } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.n_features { - return (0, Some(0)); - } - - let remaining = (self.n_features - self.idx) as usize; + let remaining = self.n_features - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.n_features - self.idx + } + + // checker-ignore-item + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.n_features || overflow { + self.idx = self.n_features; + None + } else { + unsafe { + self.idx = end + 1; + let feature = + ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), end as u32); + assert!(!feature.is_null()); + Some(CStr::from_ptr(feature).to_str().unwrap()) + } + } + } + + fn last(self) -> Option { + if self.idx == self.n_features { + None + } else { + unsafe { + let feature = ffi::gst_caps_features_get_nth( + self.caps_features.as_ptr(), + self.n_features as u32 - 1, + ); + assert!(!feature.is_null()); + Some(CStr::from_ptr(feature).to_str().unwrap()) + } + } + } } impl<'a> DoubleEndedIterator for Iter<'a> { @@ -537,18 +568,37 @@ impl<'a> DoubleEndedIterator for Iter<'a> { unsafe { let feature = - ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.n_features); - if feature.is_null() { - return None; - } + ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.n_features as u32); + assert!(!feature.is_null()); Some(CStr::from_ptr(feature).to_str().unwrap()) } } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.n_features.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.n_features; + None + } else { + unsafe { + self.n_features = end - 1; + let feature = ffi::gst_caps_features_get_nth( + self.caps_features.as_ptr(), + self.n_features as u32, + ); + assert!(!feature.is_null()); + + Some(CStr::from_ptr(feature).to_str().unwrap()) + } + } + } } impl<'a> ExactSizeIterator for Iter<'a> {} +impl<'a> std::iter::FusedIterator for Iter<'a> {} + impl<'a> IntoIterator for &'a CapsFeaturesRef { type IntoIter = Iter<'a>; type Item = &'a str; diff --git a/gstreamer/src/iterator.rs b/gstreamer/src/iterator.rs index f20977072..9a916c69c 100644 --- a/gstreamer/src/iterator.rs +++ b/gstreamer/src/iterator.rs @@ -691,6 +691,8 @@ where } } +impl iter::FusedIterator for StdIterator where for<'a> T: FromValue<'a> + 'static {} + #[cfg(test)] mod tests { use super::*; diff --git a/gstreamer/src/stream_collection.rs b/gstreamer/src/stream_collection.rs index 7adc2424a..661241f8e 100644 --- a/gstreamer/src/stream_collection.rs +++ b/gstreamer/src/stream_collection.rs @@ -13,8 +13,8 @@ use std::mem::transmute; #[derive(Debug)] pub struct Iter<'a> { collection: &'a StreamCollection, - idx: u32, - size: u32, + idx: usize, + size: usize, } impl<'a> Iter<'a> { @@ -23,7 +23,7 @@ impl<'a> Iter<'a> { Iter { collection, idx: 0, - size: collection.len() as u32, + size: collection.len() as usize, } } } @@ -36,21 +36,40 @@ impl<'a> Iterator for Iter<'a> { return None; } - let item = self.collection.stream(self.idx); + let item = self.collection.stream(self.idx as u32).unwrap(); self.idx += 1; - item + Some(item) } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.size { - return (0, Some(0)); - } - - let remaining = (self.size - self.idx) as usize; + let remaining = self.size - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.size - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.size || overflow { + self.idx = self.size; + None + } else { + self.idx = end + 1; + Some(self.collection.stream(end as u32).unwrap()) + } + } + + fn last(self) -> Option { + if self.idx == self.size { + None + } else { + Some(self.collection.stream(self.size as u32 - 1).unwrap()) + } + } } impl<'a> DoubleEndedIterator for Iter<'a> { @@ -60,12 +79,25 @@ impl<'a> DoubleEndedIterator for Iter<'a> { } self.size -= 1; - self.collection.stream(self.size) + Some(self.collection.stream(self.size as u32).unwrap()) + } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.size.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.size; + None + } else { + self.size = end - 1; + Some(self.collection.stream(self.size as u32).unwrap()) + } } } impl<'a> ExactSizeIterator for Iter<'a> {} +impl<'a> std::iter::FusedIterator for Iter<'a> {} + #[derive(Debug, Clone)] #[must_use = "The builder must be built to be used"] pub struct StreamCollectionBuilder(StreamCollection); diff --git a/gstreamer/src/structure.rs b/gstreamer/src/structure.rs index 4914ebf24..2dd933e09 100644 --- a/gstreamer/src/structure.rs +++ b/gstreamer/src/structure.rs @@ -852,8 +852,8 @@ impl glib::value::ToValueOptional for StructureRef { #[derive(Debug)] pub struct FieldIterator<'a> { structure: &'a StructureRef, - idx: u32, - n_fields: u32, + idx: usize, + n_fields: usize, } impl<'a> FieldIterator<'a> { @@ -864,7 +864,7 @@ impl<'a> FieldIterator<'a> { FieldIterator { structure, idx: 0, - n_fields, + n_fields: n_fields as usize, } } } @@ -877,20 +877,14 @@ impl<'a> Iterator for FieldIterator<'a> { return None; } - if let Some(field_name) = self.structure.nth_field_name(self.idx) { - self.idx += 1; - Some(field_name) - } else { - None - } + let field_name = self.structure.nth_field_name(self.idx as u32).unwrap(); + self.idx += 1; + + Some(field_name) } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.n_fields { - return (0, Some(0)); - } - - let remaining = (self.n_fields - self.idx) as usize; + let remaining = self.n_fields - self.idx; (remaining, Some(remaining)) } @@ -903,12 +897,14 @@ impl<'a> DoubleEndedIterator for FieldIterator<'a> { } self.n_fields -= 1; - self.structure.nth_field_name(self.n_fields) + Some(self.structure.nth_field_name(self.n_fields as u32).unwrap()) } } impl<'a> ExactSizeIterator for FieldIterator<'a> {} +impl<'a> std::iter::FusedIterator for FieldIterator<'a> {} + #[derive(Debug)] pub struct Iter<'a> { iter: FieldIterator<'a>, @@ -927,32 +923,51 @@ impl<'a> Iterator for Iter<'a> { type Item = (&'static str, &'a SendValue); fn next(&mut self) -> Option { - if let Some(f) = self.iter.next() { - let v = self.iter.structure.value(f); - Some((f, v.unwrap())) - } else { - None - } + let f = self.iter.next()?; + let v = self.iter.structure.value(f); + Some((f, v.unwrap())) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + fn count(self) -> usize { + self.iter.count() + } + + fn nth(&mut self, n: usize) -> Option { + let f = self.iter.nth(n)?; + let v = self.iter.structure.value(f); + Some((f, v.unwrap())) + } + + fn last(self) -> Option { + let structure = self.iter.structure; + let f = self.iter.last()?; + let v = structure.value(f); + Some((f, v.unwrap())) + } } impl<'a> DoubleEndedIterator for Iter<'a> { fn next_back(&mut self) -> Option { - if let Some(f) = self.iter.next_back() { - let v = self.iter.structure.value(f); - Some((f, v.unwrap())) - } else { - None - } + let f = self.iter.next_back()?; + let v = self.iter.structure.value(f); + Some((f, v.unwrap())) + } + + fn nth_back(&mut self, n: usize) -> Option { + let f = self.iter.nth_back(n)?; + let v = self.iter.structure.value(f); + Some((f, v.unwrap())) } } impl<'a> ExactSizeIterator for Iter<'a> {} +impl<'a> std::iter::FusedIterator for Iter<'a> {} + impl<'a> IntoIterator for &'a StructureRef { type IntoIter = Iter<'a>; type Item = (&'static str, &'a SendValue); diff --git a/gstreamer/src/tags.rs b/gstreamer/src/tags.rs index 2f200caa7..cc818cd80 100644 --- a/gstreamer/src/tags.rs +++ b/gstreamer/src/tags.rs @@ -606,8 +606,8 @@ impl Eq for TagListRef {} #[derive(Debug)] pub struct TagIter<'a, T: Tag<'a>> { taglist: &'a TagListRef, - idx: u32, - size: u32, + idx: usize, + size: usize, phantom: PhantomData, } @@ -617,7 +617,7 @@ impl<'a, T: Tag<'a>> TagIter<'a, T> { TagIter { taglist, idx: 0, - size: taglist.size::(), + size: taglist.size::() as usize, phantom: PhantomData, } } @@ -635,21 +635,40 @@ where return None; } - let item = self.taglist.index::(self.idx); + let item = self.taglist.index::(self.idx as u32); self.idx += 1; item } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.size { - return (0, Some(0)); - } - - let remaining = (self.size - self.idx) as usize; + let remaining = self.size - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.size - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.size || overflow { + self.idx = self.size; + None + } else { + self.idx = end + 1; + self.taglist.index::(end as u32) + } + } + + fn last(self) -> Option { + if self.idx == self.size { + None + } else { + self.taglist.index::(self.size as u32 - 1) + } + } } impl<'a, T: Tag<'a>> DoubleEndedIterator for TagIter<'a, T> @@ -663,7 +682,18 @@ where } self.size -= 1; - self.taglist.index::(self.size) + self.taglist.index::(self.size as u32) + } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.size.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.size; + None + } else { + self.size = end - 1; + self.taglist.index::(self.size as u32) + } } } @@ -674,12 +704,19 @@ where { } +impl<'a, T: Tag<'a>> std::iter::FusedIterator for TagIter<'a, T> +where + >::TagType: 'a, + T: 'a, +{ +} + #[derive(Debug)] pub struct GenericTagIter<'a> { taglist: &'a TagListRef, name: &'a str, - idx: u32, - size: u32, + idx: usize, + size: usize, } impl<'a> GenericTagIter<'a> { @@ -689,7 +726,7 @@ impl<'a> GenericTagIter<'a> { taglist, name, idx: 0, - size: taglist.size_by_name(name), + size: taglist.size_by_name(name) as usize, } } } @@ -702,21 +739,40 @@ impl<'a> Iterator for GenericTagIter<'a> { return None; } - let item = self.taglist.index_generic(self.name, self.idx); + let item = self.taglist.index_generic(self.name, self.idx as u32); self.idx += 1; item } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.size { - return (0, Some(0)); - } - - let remaining = (self.size - self.idx) as usize; + let remaining = self.size - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.size - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.size || overflow { + self.idx = self.size; + None + } else { + self.idx = end + 1; + self.taglist.index_generic(self.name, end as u32) + } + } + + fn last(self) -> Option { + if self.idx == self.size { + None + } else { + self.taglist.index_generic(self.name, self.size as u32 - 1) + } + } } impl<'a> DoubleEndedIterator for GenericTagIter<'a> { @@ -726,17 +782,30 @@ impl<'a> DoubleEndedIterator for GenericTagIter<'a> { } self.size -= 1; - self.taglist.index_generic(self.name, self.size) + self.taglist.index_generic(self.name, self.size as u32) + } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.size.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.size; + None + } else { + self.size = end - 1; + self.taglist.index_generic(self.name, self.size as u32) + } } } impl<'a> ExactSizeIterator for GenericTagIter<'a> {} +impl<'a> std::iter::FusedIterator for GenericTagIter<'a> {} + #[derive(Debug)] pub struct GenericIter<'a> { taglist: &'a TagListRef, - idx: u32, - size: u32, + idx: usize, + size: usize, } impl<'a> GenericIter<'a> { @@ -746,7 +815,7 @@ impl<'a> GenericIter<'a> { GenericIter { taglist, idx: 0, - size: if size > 0 { size as u32 } else { 0 }, + size: if size > 0 { size as usize } else { 0 }, } } } @@ -759,7 +828,7 @@ impl<'a> Iterator for GenericIter<'a> { return None; } - let name = self.taglist.nth_tag_name(self.idx); + let name = self.taglist.nth_tag_name(self.idx as u32); let item = (name, self.taglist.iter_tag_generic(name)); self.idx += 1; @@ -767,14 +836,35 @@ impl<'a> Iterator for GenericIter<'a> { } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.size { - return (0, Some(0)); - } - - let remaining = (self.size - self.idx) as usize; + let remaining = self.size - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.size - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.size || overflow { + self.idx = self.size; + None + } else { + self.idx = end + 1; + let name = self.taglist.nth_tag_name(end as u32); + Some((name, self.taglist.iter_tag_generic(name))) + } + } + + fn last(self) -> Option { + if self.idx == self.size { + None + } else { + let name = self.taglist.nth_tag_name(self.size as u32 - 1); + Some((name, self.taglist.iter_tag_generic(name))) + } + } } impl<'a> DoubleEndedIterator for GenericIter<'a> { @@ -784,18 +874,32 @@ impl<'a> DoubleEndedIterator for GenericIter<'a> { } self.size -= 1; - let name = self.taglist.nth_tag_name(self.idx); + let name = self.taglist.nth_tag_name(self.idx as u32); Some((name, self.taglist.iter_tag_generic(name))) } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.size.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.size; + None + } else { + self.size = end - 1; + let name = self.taglist.nth_tag_name(self.size as u32); + Some((name, self.taglist.iter_tag_generic(name))) + } + } } impl<'a> ExactSizeIterator for GenericIter<'a> {} +impl<'a> std::iter::FusedIterator for GenericIter<'a> {} + #[derive(Debug)] pub struct Iter<'a> { taglist: &'a TagListRef, - idx: u32, - size: u32, + idx: usize, + size: usize, } impl<'a> Iter<'a> { @@ -805,7 +909,7 @@ impl<'a> Iter<'a> { Iter { taglist, idx: 0, - size: if size > 0 { size as u32 } else { 0 }, + size: if size > 0 { size as usize } else { 0 }, } } } @@ -818,7 +922,7 @@ impl<'a> Iterator for Iter<'a> { return None; } - let name = self.taglist.nth_tag_name(self.idx); + let name = self.taglist.nth_tag_name(self.idx as u32); let item = (name, self.taglist.generic(name).unwrap()); self.idx += 1; @@ -826,14 +930,35 @@ impl<'a> Iterator for Iter<'a> { } fn size_hint(&self) -> (usize, Option) { - if self.idx == self.size { - return (0, Some(0)); - } - - let remaining = (self.size - self.idx) as usize; + let remaining = self.size - self.idx; (remaining, Some(remaining)) } + + fn count(self) -> usize { + self.size - self.idx + } + + fn nth(&mut self, n: usize) -> Option { + let (end, overflow) = self.idx.overflowing_add(n); + if end >= self.size || overflow { + self.idx = self.size; + None + } else { + self.idx = end + 1; + let name = self.taglist.nth_tag_name(end as u32); + Some((name, self.taglist.generic(name).unwrap())) + } + } + + fn last(self) -> Option { + if self.idx == self.size { + None + } else { + let name = self.taglist.nth_tag_name(self.size as u32 - 1); + Some((name, self.taglist.generic(name).unwrap())) + } + } } impl<'a> DoubleEndedIterator for Iter<'a> { @@ -843,13 +968,27 @@ impl<'a> DoubleEndedIterator for Iter<'a> { } self.size -= 1; - let name = self.taglist.nth_tag_name(self.idx); + let name = self.taglist.nth_tag_name(self.idx as u32); Some((name, self.taglist.generic(name).unwrap())) } + + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.size.overflowing_sub(n); + if end <= self.idx || overflow { + self.idx = self.size; + None + } else { + self.size = end - 1; + let name = self.taglist.nth_tag_name(self.size as u32); + Some((name, self.taglist.generic(name).unwrap())) + } + } } impl<'a> ExactSizeIterator for Iter<'a> {} +impl<'a> std::iter::FusedIterator for Iter<'a> {} + #[doc(alias = "gst_tag_exists")] pub fn tag_exists(name: &str) -> bool { skip_assert_initialized!();