// This file was generated by gir (a01311c+) from gir-files (???) // DO NOT EDIT use ffi; use glib::translate::*; use glib_ffi; use glib_ffi::{gconstpointer, gpointer}; use gobject_ffi; use std::mem; use std::ptr; use glib; use glib::Value; 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); match fn { copy => |ptr| ffi::gst_iterator_copy(mut_override(ptr)), free => |ptr| ffi::gst_iterator_free(ptr), get_type => || ffi::gst_iterator_get_type(), } } impl Iterator { pub fn resync(&mut self) { unsafe { ffi::gst_iterator_resync(self.to_glib_none_mut().0); } } pub fn filter(self, func: F) -> Self where F: Fn(&glib::Value) -> bool + Send + Sync + 'static, { unsafe { let it = self.to_glib_none().0; mem::forget(self); let mut closure_value: gobject_ffi::GValue = mem::zeroed(); let func_box: Box bool + Send + Sync + 'static> = Box::new(func); gobject_ffi::g_value_init(&mut closure_value, filter_boxed_get_type()); gobject_ffi::g_value_take_boxed( &mut closure_value, Arc::into_raw(Arc::new(func_box)) as gpointer, ); let it = from_glib_full(ffi::gst_iterator_filter( it as *mut _, Some(filter_trampoline), &closure_value, )); gobject_ffi::g_value_unset(&mut closure_value); it } } pub fn find_simple(&mut self, func: F) -> Option where F: FnMut(&glib::Value) -> bool, { unsafe { let mut elem = glib::Value::uninitialized(); let mut func = func; let func_obj: &mut (FnMut(&glib::Value) -> bool) = &mut func; let func_ptr = &func_obj as *const &mut (FnMut(&glib::Value) -> bool) as gpointer; let res = from_glib(ffi::gst_iterator_find_custom( self.to_glib_none_mut().0, Some(find_trampoline), elem.to_glib_none_mut().0, func_ptr, )); if res { Some(elem) } else { None } } } pub fn foreach(&mut self, func: F) -> Result<(), IteratorError> where F: FnMut(&glib::Value), { unsafe { let mut func = func; let func_obj: &mut (FnMut(&glib::Value)) = &mut func; let func_ptr = &func_obj as *const &mut (FnMut(&glib::Value)) as gpointer; 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_with_early_exit(&mut self, init: T, func: F) -> Result where F: FnMut(T, &glib::Value) -> Result, { unsafe { let mut func = func; let func_obj: &mut (FnMut(T, &glib::Value) -> Result) = &mut func; let func_ptr = &func_obj as *const &mut (FnMut(T, &glib::Value) -> Result) as gpointer; let mut ret = glib::Value::uninitialized(); let mut accum = Some(init); gobject_ffi::g_value_init(ret.to_glib_none_mut().0, gobject_ffi::G_TYPE_POINTER); gobject_ffi::g_value_set_pointer( ret.to_glib_none_mut().0, &mut accum as *mut _ as gpointer, ); 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 { 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), } } } pub fn new(imp: I) -> Self { static DUMMY_COOKIE: u32 = 0; unsafe { let it = ffi::gst_iterator_new( mem::size_of::>() as u32, I::item_type().to_glib(), ptr::null_mut(), &DUMMY_COOKIE as *const _ as *mut _, Some(rs_iterator_copy::), Some(rs_iterator_next::), None, Some(rs_iterator_resync::), Some(rs_iterator_free::), ); { let it = it as *mut RsIterator; (*it).imp = Some(imp); } from_glib_full(it) } } pub fn from_vec( items: Vec, ) -> Self { Self::new(VecIteratorImpl::new(items)) } } 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, imp: Option, } pub trait IteratorImpl: Clone + Send + 'static { fn item_type() -> glib::Type; fn next(&mut self) -> Option>; fn resync(&mut self); } unsafe extern "C" fn rs_iterator_copy( it: *const ffi::GstIterator, copy: *mut ffi::GstIterator, ) { callback_guard!(); let it = it as *const RsIterator; let copy = copy as *mut RsIterator; ptr::write(&mut (*copy).imp, (*it).imp.clone()); } unsafe extern "C" fn rs_iterator_free(it: *mut ffi::GstIterator) { callback_guard!(); let it = it as *mut RsIterator; let _ = (*it).imp.take(); } unsafe extern "C" fn rs_iterator_next( it: *mut ffi::GstIterator, result: *mut gobject_ffi::GValue, ) -> ffi::GstIteratorResult { callback_guard!(); let it = it as *mut RsIterator; match (*it).imp.as_mut().map(|imp| imp.next()).unwrap() { Some(Ok(value)) => { ptr::write(result, ptr::read(value.to_glib_none().0)); mem::forget(value); ffi::GST_ITERATOR_OK } None => ffi::GST_ITERATOR_DONE, Some(Err(res)) => match res { IteratorError::Resync => ffi::GST_ITERATOR_RESYNC, IteratorError::Error => ffi::GST_ITERATOR_ERROR, }, } } unsafe extern "C" fn rs_iterator_resync(it: *mut ffi::GstIterator) { callback_guard!(); let it = it as *mut RsIterator; (*it).imp.as_mut().map(|imp| imp.resync()).unwrap(); } #[derive(Clone)] struct VecIteratorImpl { pos: usize, items: Vec, } impl VecIteratorImpl { fn new(items: Vec) -> Self { Self { pos: 0, items: items, } } } impl IteratorImpl for VecIteratorImpl { fn item_type() -> glib::Type { T::static_type() } 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 Some(res); } None } fn resync(&mut self) { self.pos = 0; } } unsafe impl Send for Iterator {} unsafe extern "C" fn filter_trampoline(value: gconstpointer, func: gconstpointer) -> i32 { callback_guard!(); let value = value as *const gobject_ffi::GValue; let func = func as *const gobject_ffi::GValue; let func = gobject_ffi::g_value_get_boxed(func); #[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))] let func: &&(Fn(&glib::Value) -> bool + Send + Sync + 'static) = mem::transmute(func); let value = &*(value as *const glib::Value); if func(value) { 0 } else { -1 } } unsafe extern "C" fn filter_boxed_ref(boxed: gpointer) -> gpointer { callback_guard!(); let boxed = Arc::from_raw( boxed as *const (Box bool + Send + Sync + 'static>), ); let copy = boxed.clone(); // Forget it and keep it alive, we will still need it later let _ = Arc::into_raw(boxed); Arc::into_raw(copy) as gpointer } unsafe extern "C" fn filter_boxed_unref(boxed: gpointer) { callback_guard!(); let _ = Arc::from_raw( boxed as *const (Box bool + Send + Sync + 'static>), ); } unsafe extern "C" fn filter_boxed_get_type() -> glib_ffi::GType { use std::sync::{Once, ONCE_INIT}; callback_guard!(); static mut TYPE: glib_ffi::GType = gobject_ffi::G_TYPE_INVALID; static ONCE: Once = ONCE_INIT; ONCE.call_once(|| { let type_name = { let mut idx = 0; loop { let type_name = CString::new(format!("GstRsIteratorFilterBoxed-{}", idx)).unwrap(); if gobject_ffi::g_type_from_name(type_name.as_ptr()) == gobject_ffi::G_TYPE_INVALID { break type_name; } idx += 1; } }; TYPE = gobject_ffi::g_boxed_type_register_static( type_name.as_ptr(), Some(filter_boxed_ref), Some(filter_boxed_unref), ); }); TYPE } unsafe extern "C" fn find_trampoline(value: gconstpointer, func: gconstpointer) -> i32 { callback_guard!(); let value = value as *const gobject_ffi::GValue; let func = func as *const &mut (FnMut(&glib::Value) -> bool); let value = &*(value as *const glib::Value); if (*func)(value) { 0 } else { -1 } } unsafe extern "C" fn foreach_trampoline(value: *const gobject_ffi::GValue, func: gpointer) { callback_guard!(); let func = func as *const &mut (FnMut(&glib::Value)); let value = &*(value as *const glib::Value); (*func)(value); } unsafe extern "C" fn fold_trampoline( value: *const gobject_ffi::GValue, ret: *mut gobject_ffi::GValue, func: gpointer, ) -> glib_ffi::gboolean { callback_guard!(); let func = func as *const &mut (FnMut(T, &glib::Value) -> Result); let value = &*(value as *const glib::Value); let accum = &mut *(gobject_ffi::g_value_get_pointer(ret) as *mut Option); match (*func)(accum.take().unwrap(), value) { Ok(next_accum) => { *accum = Some(next_accum); glib_ffi::GTRUE } Err(next_accum) => { *accum = Some(next_accum); glib_ffi::GFALSE } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_vec() { ::init().unwrap(); 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 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 mut it = Iterator::from_vec(vec); let mut vals = Vec::new(); while let Some(res) = it.next() { match res { Ok(v) => vals.push(v.get::().unwrap()), _ => unreachable!(), } } 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] fn test_filter() { ::init().unwrap(); let vec = vec![1i32, 2, 3]; 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_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] fn test_foreach() { ::init().unwrap(); 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, Ok(())); assert_eq!(sum, 6); } #[test] fn test_fold() { ::init().unwrap(); // Our fold let vec = vec![1i32, 2, 3]; 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); } }