From f7bce553cdf74f1a5fe44d00b4dab8c3f3f5ccf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 17 Sep 2017 14:39:17 +0300 Subject: [PATCH] Implement std::iter::Iterator for gst::Iterator --- Gir_Gst.toml | 1 - gstreamer/src/auto/enums.rs | 63 ---------------- gstreamer/src/auto/mod.rs | 1 - gstreamer/src/iterator.rs | 143 +++++++++++++++++++++++------------- gstreamer/src/lib.rs | 2 +- 5 files changed, 92 insertions(+), 118 deletions(-) diff --git a/Gir_Gst.toml b/Gir_Gst.toml index d66a89c13..c59a88a06 100644 --- a/Gir_Gst.toml +++ b/Gir_Gst.toml @@ -55,7 +55,6 @@ generate = [ "Gst.SegmentFlags", "Gst.PadMode", "Gst.SchedulingFlags", - "Gst.IteratorResult", "Gst.ChildProxy", "Gst.Preset", "Gst.TagSetter", diff --git a/gstreamer/src/auto/enums.rs b/gstreamer/src/auto/enums.rs index 69e6869b1..37b9ad562 100644 --- a/gstreamer/src/auto/enums.rs +++ b/gstreamer/src/auto/enums.rs @@ -836,69 +836,6 @@ impl SetValue for Format { } } -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] -pub enum IteratorResult { - Done, - Ok, - Resync, - Error, - #[doc(hidden)] - __Unknown(i32), -} - -#[doc(hidden)] -impl ToGlib for IteratorResult { - type GlibType = ffi::GstIteratorResult; - - fn to_glib(&self) -> ffi::GstIteratorResult { - match *self { - IteratorResult::Done => ffi::GST_ITERATOR_DONE, - IteratorResult::Ok => ffi::GST_ITERATOR_OK, - IteratorResult::Resync => ffi::GST_ITERATOR_RESYNC, - IteratorResult::Error => ffi::GST_ITERATOR_ERROR, - IteratorResult::__Unknown(value) => unsafe{std::mem::transmute(value)} - } - } -} - -#[doc(hidden)] -impl FromGlib for IteratorResult { - fn from_glib(value: ffi::GstIteratorResult) -> Self { - skip_assert_initialized!(); - match value as i32 { - 0 => IteratorResult::Done, - 1 => IteratorResult::Ok, - 2 => IteratorResult::Resync, - 3 => IteratorResult::Error, - value => IteratorResult::__Unknown(value), - } - } -} - -impl StaticType for IteratorResult { - fn static_type() -> Type { - unsafe { from_glib(ffi::gst_iterator_result_get_type()) } - } -} - -impl<'a> FromValueOptional<'a> for IteratorResult { - unsafe fn from_value_optional(value: &Value) -> Option { - Some(FromValue::from_value(value)) - } -} - -impl<'a> FromValue<'a> for IteratorResult { - unsafe fn from_value(value: &Value) -> Self { - from_glib(std::mem::transmute::(gobject_ffi::g_value_get_enum(value.to_glib_none().0))) - } -} - -impl SetValue for IteratorResult { - unsafe fn set_value(value: &mut Value, this: &Self) { - gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib() as i32) - } -} - #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] pub enum LibraryError { Failed, diff --git a/gstreamer/src/auto/mod.rs b/gstreamer/src/auto/mod.rs index 9487746d3..dc5d2d039 100644 --- a/gstreamer/src/auto/mod.rs +++ b/gstreamer/src/auto/mod.rs @@ -108,7 +108,6 @@ pub use self::enums::DebugLevel; pub use self::enums::EventType; pub use self::enums::FlowReturn; pub use self::enums::Format; -pub use self::enums::IteratorResult; pub use self::enums::LibraryError; pub use self::enums::PadDirection; pub use self::enums::PadLinkReturn; diff --git a/gstreamer/src/iterator.rs b/gstreamer/src/iterator.rs index 33d401e5a..1d5842730 100644 --- a/gstreamer/src/iterator.rs +++ b/gstreamer/src/iterator.rs @@ -10,9 +10,15 @@ use std::mem; use std::ptr; use glib; use glib::Value; -use IteratorResult; use std::sync::Arc; use std::ffi::CString; +use std::iter::Iterator as StdIterator; + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub enum IteratorError { + Resync, + Error, +} glib_wrapper! { pub struct Iterator(Boxed); @@ -25,22 +31,6 @@ glib_wrapper! { } impl Iterator { - #[cfg_attr(feature = "cargo-clippy", allow(should_implement_trait))] - pub fn next(&mut self) -> Result { - unsafe { - let mut value = Value::uninitialized(); - let res = from_glib(ffi::gst_iterator_next( - self.to_glib_none_mut().0, - value.to_glib_none_mut().0, - )); - if res == IteratorResult::Ok { - Ok(value) - } else { - Err(res) - } - } - } - pub fn resync(&mut self) { unsafe { ffi::gst_iterator_resync(self.to_glib_none_mut().0); @@ -74,7 +64,7 @@ impl Iterator { } } - pub fn find(&mut self, func: F) -> Option + pub fn find_simple(&mut self, func: F) -> Option where F: FnMut(&glib::Value) -> bool, { @@ -99,7 +89,7 @@ impl Iterator { } } - pub fn foreach(&mut self, func: F) -> IteratorResult + pub fn foreach(&mut self, func: F) -> Result<(), IteratorError> where F: FnMut(&glib::Value), { @@ -108,15 +98,21 @@ impl Iterator { let func_obj: &mut (FnMut(&glib::Value)) = &mut func; let func_ptr = &func_obj as *const &mut (FnMut(&glib::Value)) as gpointer; - from_glib(ffi::gst_iterator_foreach( + let res = ffi::gst_iterator_foreach( self.to_glib_none_mut().0, Some(foreach_trampoline), func_ptr, - )) + ); + + match res { + ffi::GST_ITERATOR_OK | ffi::GST_ITERATOR_DONE => Ok(()), + ffi::GST_ITERATOR_RESYNC => Err(IteratorError::Resync), + ffi::GST_ITERATOR_ERROR => Err(IteratorError::Error), + } } } - pub fn fold(&mut self, init: T, func: F) -> Result + pub fn fold_with_early_exit(&mut self, init: T, func: F) -> Result where F: FnMut(T, &glib::Value) -> Result, { @@ -134,18 +130,19 @@ impl Iterator { &mut accum as *mut _ as gpointer, ); - let res = from_glib(ffi::gst_iterator_fold( + let res = ffi::gst_iterator_fold( self.to_glib_none_mut().0, Some(fold_trampoline::), ret.to_glib_none_mut().0, func_ptr, - )); + ); gobject_ffi::g_value_unset(ret.to_glib_none_mut().0); match res { - IteratorResult::Ok | IteratorResult::Done => Ok(accum.unwrap()), - _ => Err(res), + ffi::GST_ITERATOR_OK | ffi::GST_ITERATOR_DONE => Ok(accum.unwrap()), + ffi::GST_ITERATOR_RESYNC => Err(IteratorError::Resync), + ffi::GST_ITERATOR_ERROR => Err(IteratorError::Error), } } } @@ -182,6 +179,23 @@ impl Iterator { } } +impl StdIterator for Iterator { + type Item = Result; + + fn next(&mut self) -> Option> { + unsafe { + let mut value = Value::uninitialized(); + let res = ffi::gst_iterator_next(self.to_glib_none_mut().0, value.to_glib_none_mut().0); + match res { + ffi::GST_ITERATOR_OK => Some(Ok(value)), + ffi::GST_ITERATOR_DONE => None, + ffi::GST_ITERATOR_RESYNC => Some(Err(IteratorError::Resync)), + ffi::GST_ITERATOR_ERROR => Some(Err(IteratorError::Error)), + } + } + } +} + #[repr(C)] struct RsIterator { iter: ffi::GstIterator, @@ -190,7 +204,7 @@ struct RsIterator { pub trait IteratorImpl: Clone + Send + 'static { fn item_type() -> glib::Type; - fn next(&mut self) -> Result; + fn next(&mut self) -> Option>; fn resync(&mut self); } @@ -218,15 +232,16 @@ unsafe extern "C" fn rs_iterator_next( callback_guard!(); let it = it as *mut RsIterator; match (*it).imp.as_mut().map(|imp| imp.next()).unwrap() { - Ok(value) => { + Some(Ok(value)) => { ptr::write(result, ptr::read(value.to_glib_none().0)); mem::forget(value); ffi::GST_ITERATOR_OK } - Err(res) => { - assert_ne!(res, IteratorResult::Ok); - res.to_glib() - } + None => ffi::GST_ITERATOR_DONE, + Some(Err(res)) => match res { + IteratorError::Resync => ffi::GST_ITERATOR_RESYNC, + IteratorError::Error => ffi::GST_ITERATOR_ERROR, + }, } } @@ -257,14 +272,14 @@ impl Iterat T::static_type() } - fn next(&mut self) -> Result { + fn next(&mut self) -> Option> { if self.pos < self.items.len() { let res = Ok(self.items[self.pos].clone().to_value()); self.pos += 1; - return res; + return Some(res); } - Err(IteratorResult::Done) + None } fn resync(&mut self) { @@ -401,14 +416,26 @@ mod tests { let vec = vec![1i32, 2, 3]; let mut it = Iterator::from_vec(vec); + let val = it.next().unwrap(); + assert_eq!(val.unwrap().get::().unwrap(), 1); + let val = it.next().unwrap(); + assert_eq!(val.unwrap().get::().unwrap(), 2); + let val = it.next().unwrap(); + assert_eq!(val.unwrap().get::().unwrap(), 3); + assert!(it.next().is_none()); - let val = it.next().unwrap(); - assert_eq!(val.get::().unwrap(), 1); - let val = it.next().unwrap(); - assert_eq!(val.get::().unwrap(), 2); - let val = it.next().unwrap(); - assert_eq!(val.get::().unwrap(), 3); - assert_eq!(it.next().unwrap_err(), IteratorResult::Done); + let vec = vec![1i32, 2, 3]; + let it = Iterator::from_vec(vec); + let vals: Vec<_> = it.map(|v| v.unwrap().get::().unwrap()).collect(); + assert_eq!(vals, [1, 2, 3]); + + let vec = vec![1i32, 2, 3]; + let it = Iterator::from_vec(vec); + let mut vals = Vec::new(); + for v in it { + vals.push(v.unwrap().get::().unwrap()); + } + assert_eq!(vals, [1, 2, 3]); } #[test] @@ -416,22 +443,25 @@ mod tests { ::init().unwrap(); let vec = vec![1i32, 2, 3]; - let mut it = Iterator::from_vec(vec).filter(|val| val.get::().unwrap() % 2 == 1); - - let val = it.next().unwrap(); - assert_eq!(val.get::().unwrap(), 1); - let val = it.next().unwrap(); - assert_eq!(val.get::().unwrap(), 3); - assert_eq!(it.next().unwrap_err(), IteratorResult::Done); + let it = Iterator::from_vec(vec).filter(|val| val.get::().unwrap() % 2 == 1); + let vals: Vec<_> = it.map(|v| v.unwrap().get::().unwrap()).collect(); + assert_eq!(vals, [1, 3]); } #[test] fn test_find() { ::init().unwrap(); + // Our find let vec = vec![1i32, 2, 3]; - let val = Iterator::from_vec(vec).find(|val| val.get::().unwrap() == 2); + let val = Iterator::from_vec(vec).find_simple(|val| val.get::().unwrap() == 2); assert_eq!(val.unwrap().get::().unwrap(), 2); + + // Find from std::iter::Iterator + let vec = vec![1i32, 2, 3]; + let val = + Iterator::from_vec(vec).find(|val| val.as_ref().unwrap().get::().unwrap() == 2); + assert_eq!(val.unwrap().unwrap().get::().unwrap(), 2); } #[test] @@ -441,7 +471,7 @@ mod tests { let vec = vec![1i32, 2, 3]; let mut sum = 0; let res = Iterator::from_vec(vec).foreach(|val| sum += val.get::().unwrap()); - assert_eq!(res, IteratorResult::Done); + assert_eq!(res, Ok(())); assert_eq!(sum, 6); } @@ -449,11 +479,20 @@ mod tests { fn test_fold() { ::init().unwrap(); + // Our fold let vec = vec![1i32, 2, 3]; - let res = Iterator::from_vec(vec).fold(0, |mut sum, val| { + let res = Iterator::from_vec(vec).fold_with_early_exit(0, |mut sum, val| { sum += val.get::().unwrap(); Ok(sum) }); assert_eq!(res.unwrap(), 6); + + // Fold from std::iter::Iterator + let vec = vec![1i32, 2, 3]; + let res = Iterator::from_vec(vec).fold(0, |mut sum, val| { + sum += val.unwrap().get::().unwrap(); + sum + }); + assert_eq!(res, 6); } } diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index af4387da9..9169ab70a 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -104,7 +104,7 @@ pub use pad::{PadExtManual, PadProbeData, PadProbeId, PadProbeInfo, PAD_PROBE_ID pub use gobject::GObjectExtManualGst; pub use child_proxy::ChildProxyExtManual; pub use tag_setter::TagSetterExtManual; -pub use self::iterator::Iterator; +pub use self::iterator::{Iterator, IteratorError}; pub use device_provider::DeviceProviderExtManual; pub use parse_context::ParseContext; #[cfg(feature = "futures")]