From 154e996e2d98ead732d714f3d77360b155b92bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 20 Apr 2017 20:28:03 +0100 Subject: [PATCH] Implement Iterator::size_hint(), ExactSizeIterator and DoubleEndedIterator for our iterators --- gst-plugin/src/streams.rs | 33 ++++++++++++ gst-plugin/src/structure.rs | 103 ++++++++++++++++++++++++------------ gst-plugin/src/tags.rs | 23 ++++++++ 3 files changed, 126 insertions(+), 33 deletions(-) diff --git a/gst-plugin/src/streams.rs b/gst-plugin/src/streams.rs index cebfb204..a7893d1d 100644 --- a/gst-plugin/src/streams.rs +++ b/gst-plugin/src/streams.rs @@ -199,8 +199,41 @@ impl<'a> Iterator for StreamCollectionIterator<'a> { Stream(gst::gst_object_ref(stream as *mut gst::GstObject) as *mut gst::GstStream) }) } + + fn size_hint(&self) -> (usize, Option) { + if self.position == self.length { + return (0, Some(0)); + } + + let remaining = (self.length - self.position) as usize; + + (remaining, Some(remaining)) + } } +impl<'a> DoubleEndedIterator for StreamCollectionIterator<'a> { + fn next_back(&mut self) -> Option { + if self.position == self.length { + return None; + } + + self.length -= 1; + + let stream = + unsafe { gst::gst_stream_collection_get_stream(self.collection.0, self.length) }; + if stream.is_null() { + self.position = self.length; + return None; + } + + Some(unsafe { + Stream(gst::gst_object_ref(stream as *mut gst::GstObject) as *mut gst::GstStream) + }) + } +} + +impl<'a> ExactSizeIterator for StreamCollectionIterator<'a> {} + impl Clone for StreamCollection { fn clone(&self) -> Self { unsafe { diff --git a/gst-plugin/src/structure.rs b/gst-plugin/src/structure.rs index 6ca3dbb0..30294709 100644 --- a/gst-plugin/src/structure.rs +++ b/gst-plugin/src/structure.rs @@ -116,6 +116,22 @@ impl Structure { pub fn iter<'a>(&'a self) -> Iter<'a> { Iter::new(self) } + + fn get_nth_field_name<'a>(&'a self, idx: u32) -> Option<&'a str> { + unsafe { + let field_name = gst::gst_structure_nth_field_name(self.0, idx); + if field_name.is_null() { + return None; + } + + let cstr = CStr::from_ptr(field_name); + Some(cstr.to_str().unwrap()) + } + } + + fn n_fields(&self) -> u32 { + unsafe { gst::gst_structure_n_fields(self.0) as u32 } + } } impl Clone for Structure { @@ -152,7 +168,7 @@ pub struct FieldIterator<'a> { impl<'a> FieldIterator<'a> { pub fn new(structure: &'a Structure) -> FieldIterator<'a> { - let n_fields = unsafe { gst::gst_structure_n_fields(structure.0) } as u32; + let n_fields = structure.n_fields(); FieldIterator { structure: structure, @@ -170,34 +186,49 @@ impl<'a> Iterator for FieldIterator<'a> { return None; } - unsafe { - let field_name = gst::gst_structure_nth_field_name(self.structure.0, self.idx); - if field_name.is_null() { - return None; - } + if let Some(field_name) = self.structure.get_nth_field_name(self.idx) { self.idx += 1; + Some(field_name) + } else { + None + } + } - let cstr = CStr::from_ptr(field_name); - Some(cstr.to_str().unwrap()) + 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; + + (remaining, Some(remaining)) + } +} + +impl<'a> DoubleEndedIterator for FieldIterator<'a> { + fn next_back(&mut self) -> Option { + if self.idx == self.n_fields { + return None; + } + + self.n_fields -= 1; + if let Some(field_name) = self.structure.get_nth_field_name(self.n_fields) { + Some(field_name) + } else { + None } } } +impl<'a> ExactSizeIterator for FieldIterator<'a> {} + pub struct Iter<'a> { - structure: &'a Structure, - idx: u32, - n_fields: u32, + iter: FieldIterator<'a>, } impl<'a> Iter<'a> { pub fn new(structure: &'a Structure) -> Iter<'a> { - let n_fields = unsafe { gst::gst_structure_n_fields(structure.0) } as u32; - - Iter { - structure: structure, - idx: 0, - n_fields: n_fields, - } + Iter { iter: FieldIterator::new(structure) } } } @@ -205,26 +236,32 @@ impl<'a> Iterator for Iter<'a> { type Item = (&'a str, ValueRef<'a>); fn next(&mut self) -> Option<(&'a str, ValueRef<'a>)> { - if self.idx >= self.n_fields { - return None; - } - - unsafe { - let field_name = gst::gst_structure_nth_field_name(self.structure.0, self.idx); - if field_name.is_null() { - return None; - } - self.idx += 1; - - let cstr = CStr::from_ptr(field_name); - let f = cstr.to_str().unwrap(); - let v = self.structure.get_value(f); - + if let Some(f) = self.iter.next() { + let v = self.iter.structure.get_value(f); Some((f, v.unwrap())) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +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.get_value(f); + Some((f, v.unwrap())) + } else { + None } } } +impl<'a> ExactSizeIterator for Iter<'a> {} + #[cfg(test)] mod tests { use super::*; diff --git a/gst-plugin/src/tags.rs b/gst-plugin/src/tags.rs index f6dd8b54..d6da7ba7 100644 --- a/gst-plugin/src/tags.rs +++ b/gst-plugin/src/tags.rs @@ -215,8 +215,31 @@ impl<'a, T: Tag<'a>> Iterator for TagIterator<'a, T> { item } + + fn size_hint(&self) -> (usize, Option) { + if self.idx == self.size { + return (0, Some(0)); + } + + let remaining = (self.size - self.idx) as usize; + + (remaining, Some(remaining)) + } } +impl<'a, T: Tag<'a>> DoubleEndedIterator for TagIterator<'a, T> { + fn next_back(&mut self) -> Option { + if self.idx == self.size { + return None; + } + + self.size -= 1; + self.taglist.get_index::(self.size) + } +} + +impl<'a, T: Tag<'a>> ExactSizeIterator for TagIterator<'a, T> {} + #[cfg(test)] mod tests { use super::*;