gstreamer/
iterator.rs

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