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