1 // Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8 
9 use glib;
10 use glib::translate::*;
11 use glib::value::{FromValueOptional, ToValue};
12 use glib::StaticType;
13 use glib::Value;
14 use glib_sys;
15 use glib_sys::{gconstpointer, gpointer};
16 use gobject_sys;
17 use gst_sys;
18 use std::collections::HashMap;
19 use std::error::Error;
20 use std::ffi::CString;
21 use std::fmt;
22 use std::iter;
23 use std::marker::PhantomData;
24 use std::mem;
25 use std::ptr;
26 use std::sync::{Arc, Mutex};
27 
28 #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
29 pub enum IteratorError {
30     Resync,
31     Error,
32 }
33 
34 impl fmt::Display for IteratorError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result35     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36         match *self {
37             IteratorError::Resync => write!(f, "Resync"),
38             IteratorError::Error => write!(f, "Error"),
39         }
40     }
41 }
42 
43 impl Error for IteratorError {
description(&self) -> &str44     fn description(&self) -> &str {
45         match *self {
46             IteratorError::Resync => "Resync",
47             IteratorError::Error => "Error",
48         }
49     }
50 }
51 
52 // Implemented manually so that we can use generics for the item
53 pub struct Iterator<T> {
54     iter: ptr::NonNull<gst_sys::GstIterator>,
55     borrowed: bool,
56     phantom: PhantomData<T>,
57 }
58 
59 impl<T> Iterator<T>
60 where
61     for<'a> T: FromValueOptional<'a> + 'static,
62 {
into_ptr(self) -> *mut gst_sys::GstIterator63     pub unsafe fn into_ptr(self) -> *mut gst_sys::GstIterator {
64         let s = mem::ManuallyDrop::new(self);
65         let it = s.to_glib_none().0;
66         it as *mut _
67     }
68 
69     #[allow(clippy::should_implement_trait)]
next(&mut self) -> Result<Option<T>, IteratorError>70     pub fn next(&mut self) -> Result<Option<T>, IteratorError> {
71         unsafe {
72             let mut value = Value::uninitialized();
73             let res =
74                 gst_sys::gst_iterator_next(self.to_glib_none_mut().0, value.to_glib_none_mut().0);
75             match res {
76                 gst_sys::GST_ITERATOR_OK => match value.get::<T>().expect("Iterator::next") {
77                     Some(value) => Ok(Some(value)),
78                     None => Err(IteratorError::Error),
79                 },
80                 gst_sys::GST_ITERATOR_DONE => Ok(None),
81                 gst_sys::GST_ITERATOR_RESYNC => Err(IteratorError::Resync),
82                 gst_sys::GST_ITERATOR_ERROR | _ => Err(IteratorError::Error),
83             }
84         }
85     }
86 
resync(&mut self)87     pub fn resync(&mut self) {
88         unsafe {
89             gst_sys::gst_iterator_resync(self.to_glib_none_mut().0);
90         }
91     }
92 
filter<F>(self, func: F) -> Self where F: Fn(T) -> bool + Send + Sync + 'static,93     pub fn filter<F>(self, func: F) -> Self
94     where
95         F: Fn(T) -> bool + Send + Sync + 'static,
96     {
97         unsafe {
98             let func_box: Box<dyn Fn(T) -> bool + Send + Sync + 'static> = Box::new(func);
99             let mut closure_value = glib::Value::from_type(from_glib(filter_boxed_get_type::<T>()));
100             gobject_sys::g_value_take_boxed(
101                 closure_value.to_glib_none_mut().0,
102                 Arc::into_raw(Arc::new(func_box)) as gpointer,
103             );
104 
105             from_glib_full(gst_sys::gst_iterator_filter(
106                 self.into_ptr(),
107                 Some(filter_trampoline::<T>),
108                 closure_value.to_glib_none().0,
109             ))
110         }
111     }
112 
find<F>(&mut self, func: F) -> Option<T> where F: FnMut(T) -> bool,113     pub fn find<F>(&mut self, func: F) -> Option<T>
114     where
115         F: FnMut(T) -> bool,
116     {
117         unsafe {
118             let mut elem = glib::Value::uninitialized();
119 
120             let mut func = func;
121             let func_ptr = &mut func as *mut F as gpointer;
122 
123             let res = from_glib(gst_sys::gst_iterator_find_custom(
124                 self.to_glib_none_mut().0,
125                 Some(find_trampoline::<T, F>),
126                 elem.to_glib_none_mut().0,
127                 func_ptr,
128             ));
129             if res {
130                 elem.get::<T>().expect("Iterator::find")
131             } else {
132                 None
133             }
134         }
135     }
136 
foreach<F>(&mut self, func: F) -> Result<(), IteratorError> where F: FnMut(T),137     pub fn foreach<F>(&mut self, func: F) -> Result<(), IteratorError>
138     where
139         F: FnMut(T),
140     {
141         unsafe {
142             let mut func = func;
143             let func_ptr = &mut func as *mut F as gpointer;
144 
145             let res = gst_sys::gst_iterator_foreach(
146                 self.to_glib_none_mut().0,
147                 Some(foreach_trampoline::<T, F>),
148                 func_ptr,
149             );
150 
151             match res {
152                 gst_sys::GST_ITERATOR_OK | gst_sys::GST_ITERATOR_DONE => Ok(()),
153                 gst_sys::GST_ITERATOR_RESYNC => Err(IteratorError::Resync),
154                 gst_sys::GST_ITERATOR_ERROR | _ => Err(IteratorError::Error),
155             }
156         }
157     }
158 
fold<F, U>(&mut self, init: U, func: F) -> Result<U, IteratorError> where F: FnMut(U, T) -> Result<U, U>,159     pub fn fold<F, U>(&mut self, init: U, func: F) -> Result<U, IteratorError>
160     where
161         F: FnMut(U, T) -> Result<U, U>,
162     {
163         unsafe {
164             let mut func = func;
165             let func_ptr = &mut func as *mut F as gpointer;
166 
167             let mut accum = Some(init);
168             let mut ret = glib::Value::from_type(glib::Type::Pointer);
169             gobject_sys::g_value_set_pointer(
170                 ret.to_glib_none_mut().0,
171                 &mut accum as *mut _ as gpointer,
172             );
173 
174             let res = gst_sys::gst_iterator_fold(
175                 self.to_glib_none_mut().0,
176                 Some(fold_trampoline::<T, U, F>),
177                 ret.to_glib_none_mut().0,
178                 func_ptr,
179             );
180 
181             match res {
182                 gst_sys::GST_ITERATOR_OK | gst_sys::GST_ITERATOR_DONE => Ok(accum.unwrap()),
183                 gst_sys::GST_ITERATOR_RESYNC => Err(IteratorError::Resync),
184                 gst_sys::GST_ITERATOR_ERROR | _ => Err(IteratorError::Error),
185             }
186         }
187     }
188 }
189 
190 impl<T> Iterator<T>
191 where
192     for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,
193 {
new<I: IteratorImpl<T>>(imp: I) -> Self194     pub fn new<I: IteratorImpl<T>>(imp: I) -> Self {
195         static DUMMY_COOKIE: u32 = 0;
196 
197         unsafe {
198             let it = gst_sys::gst_iterator_new(
199                 mem::size_of::<RsIterator<T, I>>() as u32,
200                 T::static_type().to_glib(),
201                 ptr::null_mut(),
202                 &DUMMY_COOKIE as *const _ as *mut _,
203                 Some(rs_iterator_copy::<T, I>),
204                 Some(rs_iterator_next::<T, I>),
205                 None,
206                 Some(rs_iterator_resync::<T, I>),
207                 Some(rs_iterator_free::<T, I>),
208             );
209 
210             {
211                 let it = it as *mut RsIterator<T, I>;
212                 ptr::write(&mut (*it).imp, imp);
213             }
214 
215             from_glib_full(it)
216         }
217     }
218 }
219 
220 impl<T> Iterator<T>
221 where
222     for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Clone + Send + 'static,
223 {
from_vec(items: Vec<T>) -> Self224     pub fn from_vec(items: Vec<T>) -> Self {
225         Self::new(VecIteratorImpl::new(items))
226     }
227 }
228 
229 #[repr(C)]
230 struct RsIterator<T, I: IteratorImpl<T>>
231 where
232     for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,
233 {
234     iter: gst_sys::GstIterator,
235     imp: I,
236     phantom: PhantomData<T>,
237 }
238 
239 pub trait IteratorImpl<T>: Clone + Send + 'static
240 where
241     for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,
242 {
next(&mut self) -> Option<Result<T, IteratorError>>243     fn next(&mut self) -> Option<Result<T, IteratorError>>;
resync(&mut self)244     fn resync(&mut self);
245 }
246 
rs_iterator_copy<T, I: IteratorImpl<T>>( it: *const gst_sys::GstIterator, copy: *mut gst_sys::GstIterator, ) where for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,247 unsafe extern "C" fn rs_iterator_copy<T, I: IteratorImpl<T>>(
248     it: *const gst_sys::GstIterator,
249     copy: *mut gst_sys::GstIterator,
250 ) where
251     for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,
252 {
253     let it = it as *const RsIterator<T, I>;
254     let copy = copy as *mut RsIterator<T, I>;
255 
256     ptr::write(&mut (*copy).imp, (*it).imp.clone());
257 }
258 
rs_iterator_free<T, I: IteratorImpl<T>>(it: *mut gst_sys::GstIterator) where for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,259 unsafe extern "C" fn rs_iterator_free<T, I: IteratorImpl<T>>(it: *mut gst_sys::GstIterator)
260 where
261     for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,
262 {
263     let it = it as *mut RsIterator<T, I>;
264     ptr::drop_in_place(&mut (*it).imp);
265 }
266 
rs_iterator_next<T, I: IteratorImpl<T>>( it: *mut gst_sys::GstIterator, result: *mut gobject_sys::GValue, ) -> gst_sys::GstIteratorResult where for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,267 unsafe extern "C" fn rs_iterator_next<T, I: IteratorImpl<T>>(
268     it: *mut gst_sys::GstIterator,
269     result: *mut gobject_sys::GValue,
270 ) -> gst_sys::GstIteratorResult
271 where
272     for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,
273 {
274     let it = it as *mut RsIterator<T, I>;
275     match (*it).imp.next() {
276         Some(Ok(value)) => {
277             let value = value.to_value();
278             ptr::write(result, value.into_raw());
279             gst_sys::GST_ITERATOR_OK
280         }
281         None => gst_sys::GST_ITERATOR_DONE,
282         Some(Err(res)) => match res {
283             IteratorError::Resync => gst_sys::GST_ITERATOR_RESYNC,
284             IteratorError::Error => gst_sys::GST_ITERATOR_ERROR,
285         },
286     }
287 }
288 
rs_iterator_resync<T, I: IteratorImpl<T>>(it: *mut gst_sys::GstIterator) where for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,289 unsafe extern "C" fn rs_iterator_resync<T, I: IteratorImpl<T>>(it: *mut gst_sys::GstIterator)
290 where
291     for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static,
292 {
293     let it = it as *mut RsIterator<T, I>;
294     (*it).imp.resync();
295 }
296 
297 #[derive(Clone)]
298 struct VecIteratorImpl<T> {
299     pos: usize,
300     items: Vec<T>,
301 }
302 
303 impl<T> VecIteratorImpl<T>
304 where
305     for<'a> T: StaticType + ToValue + FromValueOptional<'a> + Clone + Send + 'static,
306 {
new(items: Vec<T>) -> Self307     fn new(items: Vec<T>) -> Self {
308         Self { pos: 0, items }
309     }
310 }
311 
312 impl<T> IteratorImpl<T> for VecIteratorImpl<T>
313 where
314     for<'a> T: StaticType + ToValue + FromValueOptional<'a> + Clone + Send + 'static,
315 {
next(&mut self) -> Option<Result<T, IteratorError>>316     fn next(&mut self) -> Option<Result<T, IteratorError>> {
317         if self.pos < self.items.len() {
318             let res = Ok(self.items[self.pos].clone());
319             self.pos += 1;
320             return Some(res);
321         }
322 
323         None
324     }
325 
resync(&mut self)326     fn resync(&mut self) {
327         self.pos = 0;
328     }
329 }
330 
331 unsafe impl<T> Send for Iterator<T> {}
332 unsafe impl<T> Sync for Iterator<T> {}
333 
filter_trampoline<T>(value: gconstpointer, func: gconstpointer) -> i32 where for<'a> T: FromValueOptional<'a> + 'static,334 unsafe extern "C" fn filter_trampoline<T>(value: gconstpointer, func: gconstpointer) -> i32
335 where
336     for<'a> T: FromValueOptional<'a> + 'static,
337 {
338     let value = value as *const gobject_sys::GValue;
339 
340     let func = func as *const gobject_sys::GValue;
341     let func = gobject_sys::g_value_get_boxed(func);
342     #[allow(clippy::transmute_ptr_to_ref)]
343     let func: &&(dyn Fn(T) -> bool + Send + Sync + 'static) = mem::transmute(func);
344 
345     let value = &*(value as *const glib::Value);
346     let value = value
347         .get::<T>()
348         .expect("Iterator filter_trampoline")
349         .unwrap();
350 
351     if func(value) {
352         0
353     } else {
354         -1
355     }
356 }
357 
filter_boxed_ref<T: 'static>(boxed: gpointer) -> gpointer358 unsafe extern "C" fn filter_boxed_ref<T: 'static>(boxed: gpointer) -> gpointer {
359     let boxed = Arc::from_raw(boxed as *const Box<dyn Fn(T) -> bool + Send + Sync + 'static>);
360     let copy = Arc::clone(&boxed);
361 
362     // Forget it and keep it alive, we will still need it later
363     let _ = Arc::into_raw(boxed);
364 
365     Arc::into_raw(copy) as gpointer
366 }
367 
filter_boxed_unref<T: 'static>(boxed: gpointer)368 unsafe extern "C" fn filter_boxed_unref<T: 'static>(boxed: gpointer) {
369     let _ = Arc::from_raw(boxed as *const Box<dyn Fn(T) -> bool + Send + Sync + 'static>);
370 }
371 
372 lazy_static! {
373     static ref TYPES: Mutex<HashMap<String, glib_sys::GType>> = Mutex::new(HashMap::new());
374 }
375 
filter_boxed_get_type<T: StaticType + 'static>() -> glib_sys::GType376 unsafe extern "C" fn filter_boxed_get_type<T: StaticType + 'static>() -> glib_sys::GType {
377     let mut types = TYPES.lock().unwrap();
378     let type_name = T::static_type().name();
379 
380     if let Some(type_) = types.get(&type_name) {
381         return *type_;
382     }
383 
384     let type_ = {
385         let iter_type_name = {
386             let mut idx = 0;
387 
388             loop {
389                 let iter_type_name =
390                     CString::new(format!("GstRsIteratorFilterBoxed-{}-{}", type_name, idx))
391                         .unwrap();
392                 if gobject_sys::g_type_from_name(iter_type_name.as_ptr())
393                     == gobject_sys::G_TYPE_INVALID
394                 {
395                     break iter_type_name;
396                 }
397                 idx += 1;
398             }
399         };
400 
401         let type_ = gobject_sys::g_boxed_type_register_static(
402             iter_type_name.as_ptr(),
403             Some(filter_boxed_ref::<T>),
404             Some(filter_boxed_unref::<T>),
405         );
406 
407         assert_ne!(type_, gobject_sys::G_TYPE_INVALID);
408 
409         type_
410     };
411 
412     types.insert(type_name, type_);
413 
414     type_
415 }
416 
find_trampoline<T, F: FnMut(T) -> bool>( value: gconstpointer, func: gconstpointer, ) -> i32 where for<'a> T: FromValueOptional<'a> + 'static,417 unsafe extern "C" fn find_trampoline<T, F: FnMut(T) -> bool>(
418     value: gconstpointer,
419     func: gconstpointer,
420 ) -> i32
421 where
422     for<'a> T: FromValueOptional<'a> + 'static,
423 {
424     let value = value as *const gobject_sys::GValue;
425 
426     let func = func as *mut F;
427     let value = &*(value as *const glib::Value);
428     let value = value.get::<T>().expect("Iterator find_trampoline").unwrap();
429 
430     if (*func)(value) {
431         0
432     } else {
433         -1
434     }
435 }
436 
foreach_trampoline<T, F: FnMut(T)>( value: *const gobject_sys::GValue, func: gpointer, ) where for<'a> T: FromValueOptional<'a> + 'static,437 unsafe extern "C" fn foreach_trampoline<T, F: FnMut(T)>(
438     value: *const gobject_sys::GValue,
439     func: gpointer,
440 ) where
441     for<'a> T: FromValueOptional<'a> + 'static,
442 {
443     let func = func as *mut F;
444     let value = &*(value as *const glib::Value);
445     let value = value
446         .get::<T>()
447         .expect("Iterator foreach_trampoline")
448         .unwrap();
449 
450     (*func)(value);
451 }
452 
fold_trampoline<T, U, F: FnMut(U, T) -> Result<U, U>>( value: *const gobject_sys::GValue, ret: *mut gobject_sys::GValue, func: gpointer, ) -> glib_sys::gboolean where for<'a> T: FromValueOptional<'a> + 'static,453 unsafe extern "C" fn fold_trampoline<T, U, F: FnMut(U, T) -> Result<U, U>>(
454     value: *const gobject_sys::GValue,
455     ret: *mut gobject_sys::GValue,
456     func: gpointer,
457 ) -> glib_sys::gboolean
458 where
459     for<'a> T: FromValueOptional<'a> + 'static,
460 {
461     let func = func as *mut F;
462     let value = &*(value as *const glib::Value);
463     let value = value.get::<T>().expect("Iterator fold_trampoline").unwrap();
464 
465     let accum = &mut *(gobject_sys::g_value_get_pointer(ret) as *mut Option<U>);
466 
467     match (*func)(accum.take().unwrap(), value) {
468         Ok(next_accum) => {
469             *accum = Some(next_accum);
470             glib_sys::GTRUE
471         }
472         Err(next_accum) => {
473             *accum = Some(next_accum);
474             glib_sys::GFALSE
475         }
476     }
477 }
478 
479 impl<T: StaticType + 'static> Clone for Iterator<T> {
clone(&self) -> Self480     fn clone(&self) -> Self {
481         unsafe { from_glib_full(gst_sys::gst_iterator_copy(self.to_glib_none().0)) }
482     }
483 }
484 
485 impl<T> fmt::Debug for Iterator<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result486     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
487         f.debug_struct("Iterator")
488             .field("iter", &self.iter)
489             .field("borrowed", &self.borrowed)
490             .finish()
491     }
492 }
493 
494 impl<T> Drop for Iterator<T> {
drop(&mut self)495     fn drop(&mut self) {
496         if !self.borrowed {
497             unsafe {
498                 gst_sys::gst_iterator_free(self.iter.as_ptr());
499             }
500         }
501     }
502 }
503 
504 impl<T> iter::IntoIterator for Iterator<T>
505 where
506     for<'a> T: FromValueOptional<'a> + 'static,
507 {
508     type Item = Result<T, IteratorError>;
509     type IntoIter = StdIterator<T>;
510 
into_iter(self) -> Self::IntoIter511     fn into_iter(self) -> Self::IntoIter {
512         Self::IntoIter::new(self)
513     }
514 }
515 
516 impl<T> glib::types::StaticType for Iterator<T> {
static_type() -> glib::types::Type517     fn static_type() -> glib::types::Type {
518         unsafe { glib::translate::from_glib(gst_sys::gst_iterator_get_type()) }
519     }
520 }
521 
522 #[doc(hidden)]
523 impl<'a, T: StaticType> glib::value::FromValueOptional<'a> for Iterator<T> {
from_value_optional(value: &glib::Value) -> Option<Self>524     unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> {
525         Option::<Iterator<T>>::from_glib_none(
526             gobject_sys::g_value_get_boxed(value.to_glib_none().0) as *mut gst_sys::GstIterator,
527         )
528     }
529 }
530 
531 #[doc(hidden)]
532 impl<T: 'static> glib::value::SetValue for Iterator<T> {
set_value(value: &mut glib::Value, this: &Self)533     unsafe fn set_value(value: &mut glib::Value, this: &Self) {
534         gobject_sys::g_value_set_boxed(
535             value.to_glib_none_mut().0,
536             glib::translate::ToGlibPtr::<*const gst_sys::GstIterator>::to_glib_none(this).0
537                 as glib_sys::gpointer,
538         )
539     }
540 }
541 
542 #[doc(hidden)]
543 impl<T: 'static> glib::value::SetValueOptional for Iterator<T> {
set_value_optional(value: &mut glib::Value, this: Option<&Self>)544     unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) {
545         gobject_sys::g_value_set_boxed(
546             value.to_glib_none_mut().0,
547             glib::translate::ToGlibPtr::<*const gst_sys::GstIterator>::to_glib_none(&this).0
548                 as glib_sys::gpointer,
549         )
550     }
551 }
552 
553 #[doc(hidden)]
554 impl<T> glib::translate::GlibPtrDefault for Iterator<T> {
555     type GlibType = *mut gst_sys::GstIterator;
556 }
557 
558 #[doc(hidden)]
559 impl<'a, T: 'static> glib::translate::ToGlibPtr<'a, *const gst_sys::GstIterator> for Iterator<T> {
560     type Storage = &'a Iterator<T>;
561 
to_glib_none(&'a self) -> glib::translate::Stash<'a, *const gst_sys::GstIterator, Self>562     fn to_glib_none(&'a self) -> glib::translate::Stash<'a, *const gst_sys::GstIterator, Self> {
563         glib::translate::Stash(self.iter.as_ptr(), self)
564     }
565 
to_glib_full(&self) -> *const gst_sys::GstIterator566     fn to_glib_full(&self) -> *const gst_sys::GstIterator {
567         unimplemented!()
568     }
569 }
570 
571 #[doc(hidden)]
572 impl<'a, T: 'static> glib::translate::ToGlibPtrMut<'a, *mut gst_sys::GstIterator> for Iterator<T> {
573     type Storage = &'a mut Iterator<T>;
574 
575     #[inline]
to_glib_none_mut( &'a mut self, ) -> glib::translate::StashMut<'a, *mut gst_sys::GstIterator, Self>576     fn to_glib_none_mut(
577         &'a mut self,
578     ) -> glib::translate::StashMut<'a, *mut gst_sys::GstIterator, Self> {
579         glib::translate::StashMut(self.iter.as_ptr(), self)
580     }
581 }
582 
583 #[doc(hidden)]
584 impl<T: StaticType> glib::translate::FromGlibPtrNone<*const gst_sys::GstIterator> for Iterator<T> {
585     #[inline]
from_glib_none(ptr: *const gst_sys::GstIterator) -> Self586     unsafe fn from_glib_none(ptr: *const gst_sys::GstIterator) -> Self {
587         assert_ne!(
588             gobject_sys::g_type_is_a((*ptr).type_, T::static_type().to_glib()),
589             glib_sys::GFALSE
590         );
591         from_glib_full(gst_sys::gst_iterator_copy(ptr))
592     }
593 }
594 
595 #[doc(hidden)]
596 impl<T: StaticType> glib::translate::FromGlibPtrNone<*mut gst_sys::GstIterator> for Iterator<T> {
597     #[inline]
from_glib_none(ptr: *mut gst_sys::GstIterator) -> Self598     unsafe fn from_glib_none(ptr: *mut gst_sys::GstIterator) -> Self {
599         assert_ne!(
600             gobject_sys::g_type_is_a((*ptr).type_, T::static_type().to_glib()),
601             glib_sys::GFALSE
602         );
603         from_glib_full(gst_sys::gst_iterator_copy(ptr))
604     }
605 }
606 
607 #[doc(hidden)]
608 impl<T: StaticType> glib::translate::FromGlibPtrBorrow<*mut gst_sys::GstIterator> for Iterator<T> {
609     #[inline]
from_glib_borrow(ptr: *mut gst_sys::GstIterator) -> Self610     unsafe fn from_glib_borrow(ptr: *mut gst_sys::GstIterator) -> Self {
611         assert!(!ptr.is_null());
612         assert_ne!(
613             gobject_sys::g_type_is_a((*ptr).type_, T::static_type().to_glib()),
614             glib_sys::GFALSE
615         );
616         Self {
617             iter: ptr::NonNull::new_unchecked(ptr),
618             borrowed: true,
619             phantom: PhantomData,
620         }
621     }
622 }
623 
624 #[doc(hidden)]
625 impl<T: StaticType> glib::translate::FromGlibPtrFull<*mut gst_sys::GstIterator> for Iterator<T> {
626     #[inline]
from_glib_full(ptr: *mut gst_sys::GstIterator) -> Self627     unsafe fn from_glib_full(ptr: *mut gst_sys::GstIterator) -> Self {
628         assert!(!ptr.is_null());
629         assert_ne!(
630             gobject_sys::g_type_is_a((*ptr).type_, T::static_type().to_glib()),
631             glib_sys::GFALSE
632         );
633         Self {
634             iter: ptr::NonNull::new_unchecked(ptr),
635             borrowed: false,
636             phantom: PhantomData,
637         }
638     }
639 }
640 
641 pub struct StdIterator<T> {
642     inner: Iterator<T>,
643     error: Option<IteratorError>,
644 }
645 
646 impl<T> StdIterator<T> {
new(inner: Iterator<T>) -> Self647     fn new(inner: Iterator<T>) -> Self {
648         Self { inner, error: None }
649     }
650 }
651 
652 impl<T: StaticType + 'static> Clone for StdIterator<T> {
clone(&self) -> Self653     fn clone(&self) -> Self {
654         Self {
655             inner: self.inner.clone(),
656             error: self.error,
657         }
658     }
659 }
660 
661 impl<T> fmt::Debug for StdIterator<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result662     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
663         f.debug_struct("StdIterator")
664             .field("inner", &self.inner)
665             .field("error", &self.error)
666             .finish()
667     }
668 }
669 
670 impl<T> iter::Iterator for StdIterator<T>
671 where
672     for<'a> T: FromValueOptional<'a> + 'static,
673 {
674     type Item = Result<T, IteratorError>;
675 
next(&mut self) -> Option<Self::Item>676     fn next(&mut self) -> Option<Self::Item> {
677         match self.error {
678             // Fuse the iterator after returning IteratorError::Error
679             Some(IteratorError::Error) => return None,
680 
681             // The iterator needs a resync
682             Some(IteratorError::Resync) => self.inner.resync(),
683 
684             None => {}
685         }
686 
687         let res = self.inner.next();
688         self.error = res.as_ref().err().copied();
689         res.transpose()
690     }
691 }
692 
693 #[cfg(test)]
694 mod tests {
695     use super::*;
696 
697     #[test]
test_vec()698     fn test_vec() {
699         ::init().unwrap();
700 
701         let vec = vec![1i32, 2, 3];
702         let mut it = Iterator::from_vec(vec);
703         let val = it.next();
704         assert_eq!(val, Ok(Some(1)));
705         let val = it.next();
706         assert_eq!(val, Ok(Some(2)));
707         let val = it.next();
708         assert_eq!(val, Ok(Some(3)));
709         assert_eq!(it.next(), Ok(None));
710 
711         let vec = vec![1i32, 2, 3];
712         let mut it = Iterator::from_vec(vec);
713         let mut vals = Vec::new();
714         while let Ok(Some(res)) = it.next() {
715             vals.push(res);
716         }
717         assert_eq!(vals, [1, 2, 3]);
718     }
719 
720     #[test]
test_filter()721     fn test_filter() {
722         ::init().unwrap();
723 
724         let vec = vec![1i32, 2, 3];
725         let mut it = Iterator::from_vec(vec).filter(|val| val % 2 == 1);
726 
727         let mut vals = Vec::new();
728         while let Ok(Some(res)) = it.next() {
729             vals.push(res);
730         }
731         assert_eq!(vals, [1, 3]);
732     }
733 
734     #[test]
test_find()735     fn test_find() {
736         ::init().unwrap();
737 
738         // Our find
739         let vec = vec![1i32, 2, 3];
740         let val = Iterator::from_vec(vec).find(|val| val == 2);
741         assert_eq!(val.unwrap(), 2);
742     }
743 
744     #[test]
test_foreach()745     fn test_foreach() {
746         ::init().unwrap();
747 
748         let vec = vec![1i32, 2, 3];
749         let mut sum = 0;
750         let res = Iterator::from_vec(vec).foreach(|val| sum += val);
751         assert_eq!(res, Ok(()));
752         assert_eq!(sum, 6);
753     }
754 
755     #[test]
test_fold()756     fn test_fold() {
757         ::init().unwrap();
758 
759         // Our fold
760         let vec = vec![1i32, 2, 3];
761         let res = Iterator::from_vec(vec).fold(0, |mut sum, val| {
762             sum += val;
763             Ok(sum)
764         });
765         assert_eq!(res.unwrap(), 6);
766     }
767 
768     #[test]
test_std()769     fn test_std() {
770         let mut it = Iterator::from_vec(vec![1i32, 2, 3]).into_iter();
771         assert_eq!(it.next(), Some(Ok(1)));
772         assert_eq!(it.next(), Some(Ok(2)));
773         assert_eq!(it.next(), Some(Ok(3)));
774         assert_eq!(it.next(), None);
775     }
776 
777     #[test]
test_into_iter()778     fn test_into_iter() {
779         let mut v = vec![1i32, 2, 3].into_iter();
780         for x in Iterator::from_vec(vec![1i32, 2, 3]) {
781             assert_eq!(x.unwrap(), v.next().unwrap());
782         }
783         assert_eq!(v.next(), None);
784     }
785 
786     #[test]
test_std_resync_collect()787     fn test_std_resync_collect() {
788         use prelude::*;
789         use std::collections::BTreeSet;
790 
791         ::init().unwrap();
792 
793         let bin = ::Bin::new(None);
794         let id1 = ::ElementFactory::make("identity", None).unwrap();
795         let id2 = ::ElementFactory::make("identity", None).unwrap();
796 
797         bin.add(&id1).unwrap();
798 
799         let mut it = bin.iterate_elements().into_iter();
800         assert_eq!(it.next().unwrap().unwrap(), id1);
801 
802         bin.add(&id2).unwrap();
803 
804         let res = it.by_ref().collect::<Result<Vec<_>, _>>().unwrap_err();
805         assert_eq!(res, IteratorError::Resync);
806 
807         let mut elems = BTreeSet::new();
808         elems.insert(id1);
809         elems.insert(id2);
810 
811         let res = it.by_ref().collect::<Result<BTreeSet<_>, _>>().unwrap();
812         assert_eq!(res, elems);
813 
814         let res = it.collect::<Result<Vec<_>, _>>().unwrap();
815         assert!(res.is_empty());
816     }
817 
818     #[test]
test_std_resync_find()819     fn test_std_resync_find() {
820         use prelude::*;
821 
822         ::init().unwrap();
823 
824         let bin = ::Bin::new(None);
825         let id1 = ::ElementFactory::make("identity", None).unwrap();
826         let id2 = ::ElementFactory::make("identity", None).unwrap();
827 
828         bin.add(&id1).unwrap();
829 
830         let mut it = bin.iterate_elements().into_iter();
831         assert_eq!(it.next().unwrap().unwrap(), id1);
832 
833         bin.add(&id2).unwrap();
834 
835         let res = it.find(|x| x.as_ref() == Ok(&id1));
836         assert_eq!(res.unwrap().unwrap(), id1);
837     }
838 }
839