Skip to main content

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    Value,
8    ffi::{gconstpointer, gpointer},
9    prelude::*,
10    translate::*,
11    value::{FromValue, ToValue},
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    unsafe {
256        let it = it as *const RsIterator<T, I>;
257        let copy = copy as *mut RsIterator<T, I>;
258
259        ptr::write(&mut (*copy).imp, (*it).imp.clone());
260    }
261}
262
263unsafe extern "C" fn rs_iterator_free<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator)
264where
265    for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
266{
267    unsafe {
268        let it = it as *mut RsIterator<T, I>;
269        ptr::drop_in_place(&mut (*it).imp);
270    }
271}
272
273unsafe extern "C" fn rs_iterator_next<T, I: IteratorImpl<T>>(
274    it: *mut ffi::GstIterator,
275    result: *mut glib::gobject_ffi::GValue,
276) -> ffi::GstIteratorResult
277where
278    for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
279{
280    unsafe {
281        let it = it as *mut RsIterator<T, I>;
282        match (*it).imp.next() {
283            Some(Ok(value)) => {
284                let value = value.to_value();
285                ptr::write(result, value.into_raw());
286                ffi::GST_ITERATOR_OK
287            }
288            None => ffi::GST_ITERATOR_DONE,
289            Some(Err(res)) => match res {
290                IteratorError::Resync => ffi::GST_ITERATOR_RESYNC,
291                IteratorError::Error => ffi::GST_ITERATOR_ERROR,
292            },
293        }
294    }
295}
296
297unsafe extern "C" fn rs_iterator_resync<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator)
298where
299    for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
300{
301    unsafe {
302        let it = it as *mut RsIterator<T, I>;
303        (*it).imp.resync();
304    }
305}
306
307#[derive(Clone)]
308struct ArrayIteratorImpl<A, T> {
309    pos: usize,
310    items: A,
311    phantom: PhantomData<T>,
312}
313
314impl<T, A> ArrayIteratorImpl<A, T> {
315    fn new(items: A) -> Self {
316        skip_assert_initialized!();
317        Self {
318            pos: 0,
319            items,
320            phantom: PhantomData,
321        }
322    }
323}
324
325impl<T, A> IteratorImpl<T> for ArrayIteratorImpl<A, T>
326where
327    A: AsRef<[T]> + Send + Clone + 'static,
328    for<'a> T: StaticType + ToValue + FromValue<'a> + Clone + Send + 'static,
329{
330    fn next(&mut self) -> Option<Result<T, IteratorError>> {
331        let items = self.items.as_ref();
332        if self.pos < items.len() {
333            let res = Ok(items[self.pos].clone());
334            self.pos += 1;
335            return Some(res);
336        }
337
338        None
339    }
340
341    fn resync(&mut self) {
342        self.pos = 0;
343    }
344}
345
346#[derive(Clone)]
347struct OptionIteratorImpl<T> {
348    finished: bool,
349    items: Option<T>,
350}
351
352impl<T> OptionIteratorImpl<T> {
353    fn new(items: Option<T>) -> Self {
354        skip_assert_initialized!();
355        Self {
356            finished: false,
357            items,
358        }
359    }
360}
361
362impl<T> IteratorImpl<T> for OptionIteratorImpl<T>
363where
364    for<'a> T: StaticType + ToValue + FromValue<'a> + Clone + Send + 'static,
365{
366    fn next(&mut self) -> Option<Result<T, IteratorError>> {
367        if self.finished {
368            return None;
369        }
370        let res = Ok(self.items.clone()).transpose();
371        self.finished = true;
372        res
373    }
374
375    fn resync(&mut self) {
376        self.finished = false;
377    }
378}
379
380unsafe impl<T> Send for Iterator<T> {}
381unsafe impl<T> Sync for Iterator<T> {}
382
383unsafe extern "C" fn filter_trampoline<
384    T: for<'a> FromValue<'a> + StaticType + 'static,
385    F: Fn(T) -> bool + Send + Sync + 'static,
386>(
387    value: gconstpointer,
388    func: gconstpointer,
389) -> i32 {
390    unsafe {
391        let value = value as *const glib::gobject_ffi::GValue;
392
393        let func = func as *const glib::gobject_ffi::GValue;
394        let func = glib::gobject_ffi::g_value_get_boxed(func);
395        let func = &*(func as *const &(dyn Any + Send + Sync + 'static));
396        let func = func.downcast_ref::<F>().unwrap();
397
398        let value = &*(value as *const glib::Value);
399        let value = value.get::<T>().expect("Iterator filter_trampoline");
400
401        if func(value) { 0 } else { -1 }
402    }
403}
404
405unsafe extern "C" fn filter_boxed_ref(boxed: gpointer) -> gpointer {
406    unsafe {
407        let boxed = Arc::from_raw(boxed as *const Box<dyn Any + Send + Sync + 'static>);
408        let copy = Arc::clone(&boxed);
409
410        // Forget it and keep it alive, we will still need it later
411        let _ = Arc::into_raw(boxed);
412
413        Arc::into_raw(copy) as gpointer
414    }
415}
416
417unsafe extern "C" fn filter_boxed_unref(boxed: gpointer) {
418    unsafe {
419        let _ = Arc::from_raw(boxed as *const Box<dyn Any + Send + Sync + 'static>);
420    }
421}
422
423unsafe extern "C" fn filter_boxed_get_type() -> glib::Type {
424    unsafe {
425        static TYPE: std::sync::OnceLock<glib::Type> = std::sync::OnceLock::new();
426
427        *TYPE.get_or_init(|| {
428            let iter_type_name = {
429                let mut idx = 0;
430
431                loop {
432                    let iter_type_name = glib::gformat!("GstRsIteratorFilterBoxed-{}", idx);
433                    if glib::gobject_ffi::g_type_from_name(iter_type_name.as_ptr())
434                        == glib::gobject_ffi::G_TYPE_INVALID
435                    {
436                        break iter_type_name;
437                    }
438                    idx += 1;
439                }
440            };
441
442            let t = glib::Type::from_glib(glib::gobject_ffi::g_boxed_type_register_static(
443                iter_type_name.as_ptr(),
444                Some(filter_boxed_ref),
445                Some(filter_boxed_unref),
446            ));
447
448            assert!(t.is_valid());
449
450            t
451        })
452    }
453}
454
455unsafe extern "C" fn find_trampoline<T, F: FnMut(T) -> bool>(
456    value: gconstpointer,
457    func: gconstpointer,
458) -> i32
459where
460    for<'a> T: FromValue<'a> + 'static,
461{
462    unsafe {
463        let value = value as *const glib::gobject_ffi::GValue;
464
465        let func = func as *mut F;
466        let value = &*(value as *const glib::Value);
467        let value = value.get::<T>().expect("Iterator find_trampoline");
468
469        if (*func)(value) { 0 } else { -1 }
470    }
471}
472
473unsafe extern "C" fn foreach_trampoline<T, F: FnMut(T)>(
474    value: *const glib::gobject_ffi::GValue,
475    func: gpointer,
476) where
477    for<'a> T: FromValue<'a> + 'static,
478{
479    unsafe {
480        let func = func as *mut F;
481        let value = &*(value as *const glib::Value);
482        let value = value.get::<T>().expect("Iterator foreach_trampoline");
483
484        (*func)(value);
485    }
486}
487
488unsafe extern "C" fn fold_trampoline<T, U, F: FnMut(U, T) -> Result<U, U>>(
489    value: *const glib::gobject_ffi::GValue,
490    ret: *mut glib::gobject_ffi::GValue,
491    func: gpointer,
492) -> glib::ffi::gboolean
493where
494    for<'a> T: FromValue<'a> + 'static,
495{
496    unsafe {
497        let func = func as *mut F;
498        let value = &*(value as *const glib::Value);
499        let value = value.get::<T>().expect("Iterator fold_trampoline");
500
501        let accum = &mut *(glib::gobject_ffi::g_value_get_pointer(ret) as *mut Option<U>);
502
503        match (*func)(accum.take().unwrap(), value) {
504            Ok(next_accum) => {
505                *accum = Some(next_accum);
506                glib::ffi::GTRUE
507            }
508            Err(next_accum) => {
509                *accum = Some(next_accum);
510                glib::ffi::GFALSE
511            }
512        }
513    }
514}
515
516impl<T: StaticType + 'static> Clone for Iterator<T> {
517    #[inline]
518    fn clone(&self) -> Self {
519        unsafe { from_glib_full(ffi::gst_iterator_copy(self.to_glib_none().0)) }
520    }
521}
522
523impl<T> fmt::Debug for Iterator<T> {
524    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
525        f.debug_struct("Iterator")
526            .field("iter", &self.iter)
527            .finish()
528    }
529}
530
531impl<T> Drop for Iterator<T> {
532    #[inline]
533    fn drop(&mut self) {
534        unsafe {
535            ffi::gst_iterator_free(self.iter.as_ptr());
536        }
537    }
538}
539
540impl<T> iter::IntoIterator for Iterator<T>
541where
542    for<'a> T: FromValue<'a> + 'static,
543{
544    type Item = Result<T, IteratorError>;
545    type IntoIter = StdIterator<T>;
546
547    fn into_iter(self) -> Self::IntoIter {
548        Self::IntoIter::new(self)
549    }
550}
551
552impl<T> glib::types::StaticType for Iterator<T> {
553    #[inline]
554    fn static_type() -> glib::types::Type {
555        unsafe { glib::translate::from_glib(ffi::gst_iterator_get_type()) }
556    }
557}
558
559impl<T: StaticType + 'static> glib::value::ValueType for Iterator<T> {
560    type Type = Self;
561}
562
563impl<T: StaticType + 'static> glib::value::ValueTypeOptional for Iterator<T> {}
564
565unsafe impl<'a, T: StaticType + 'static> glib::value::FromValue<'a> for Iterator<T> {
566    type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
567
568    unsafe fn from_value(value: &'a glib::Value) -> Self {
569        unsafe {
570            skip_assert_initialized!();
571            from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
572                as *mut ffi::GstIterator)
573        }
574    }
575}
576
577impl<T: StaticType + 'static> glib::value::ToValue for Iterator<T> {
578    fn to_value(&self) -> glib::Value {
579        let mut value = glib::Value::for_value_type::<Self>();
580        unsafe {
581            glib::gobject_ffi::g_value_set_boxed(
582                value.to_glib_none_mut().0,
583                self.to_glib_none().0 as *mut _,
584            )
585        }
586        value
587    }
588
589    fn value_type(&self) -> glib::Type {
590        Self::static_type()
591    }
592}
593
594impl<T: StaticType + 'static> glib::value::ToValueOptional for Iterator<T> {
595    fn to_value_optional(s: Option<&Self>) -> glib::Value {
596        skip_assert_initialized!();
597        let mut value = glib::Value::for_value_type::<Self>();
598        unsafe {
599            glib::gobject_ffi::g_value_set_boxed(
600                value.to_glib_none_mut().0,
601                s.to_glib_none().0 as *mut _,
602            )
603        }
604        value
605    }
606}
607
608impl<T: StaticType + 'static> From<Iterator<T>> for glib::Value {
609    fn from(v: Iterator<T>) -> glib::Value {
610        skip_assert_initialized!();
611        let mut value = glib::Value::for_value_type::<Iterator<T>>();
612        unsafe {
613            glib::gobject_ffi::g_value_take_boxed(
614                value.to_glib_none_mut().0,
615                v.into_glib_ptr() as *mut _,
616            )
617        }
618        value
619    }
620}
621
622#[doc(hidden)]
623impl<T> glib::translate::GlibPtrDefault for Iterator<T> {
624    type GlibType = *mut ffi::GstIterator;
625}
626
627#[doc(hidden)]
628unsafe impl<T: StaticType + 'static> TransparentPtrType for Iterator<T> {}
629
630#[doc(hidden)]
631impl<'a, T: 'static> glib::translate::ToGlibPtr<'a, *const ffi::GstIterator> for Iterator<T> {
632    type Storage = PhantomData<&'a Iterator<T>>;
633
634    #[inline]
635    fn to_glib_none(&'a self) -> glib::translate::Stash<'a, *const ffi::GstIterator, Self> {
636        glib::translate::Stash(self.iter.as_ptr(), PhantomData)
637    }
638
639    fn to_glib_full(&self) -> *const ffi::GstIterator {
640        unimplemented!()
641    }
642}
643
644#[doc(hidden)]
645impl<'a, T: 'static> glib::translate::ToGlibPtrMut<'a, *mut ffi::GstIterator> for Iterator<T> {
646    type Storage = PhantomData<&'a mut Iterator<T>>;
647
648    #[inline]
649    fn to_glib_none_mut(
650        &'a mut self,
651    ) -> glib::translate::StashMut<'a, *mut ffi::GstIterator, Self> {
652        glib::translate::StashMut(self.iter.as_ptr(), PhantomData)
653    }
654}
655
656#[doc(hidden)]
657impl<T: StaticType> glib::translate::FromGlibPtrNone<*const ffi::GstIterator> for Iterator<T> {
658    #[inline]
659    unsafe fn from_glib_none(ptr: *const ffi::GstIterator) -> Self {
660        unsafe {
661            debug_assert_ne!(
662                glib::gobject_ffi::g_type_is_a((*ptr).type_, T::static_type().into_glib()),
663                glib::ffi::GFALSE
664            );
665            from_glib_full(ffi::gst_iterator_copy(ptr))
666        }
667    }
668}
669
670#[doc(hidden)]
671impl<T: StaticType> glib::translate::FromGlibPtrNone<*mut ffi::GstIterator> for Iterator<T> {
672    #[inline]
673    unsafe fn from_glib_none(ptr: *mut ffi::GstIterator) -> Self {
674        unsafe {
675            debug_assert_ne!(
676                glib::gobject_ffi::g_type_is_a((*ptr).type_, T::static_type().into_glib()),
677                glib::ffi::GFALSE
678            );
679            from_glib_full(ffi::gst_iterator_copy(ptr))
680        }
681    }
682}
683
684#[doc(hidden)]
685impl<T: StaticType> glib::translate::FromGlibPtrBorrow<*mut ffi::GstIterator> for Iterator<T> {
686    #[inline]
687    unsafe fn from_glib_borrow(ptr: *mut ffi::GstIterator) -> Borrowed<Self> {
688        unsafe {
689            debug_assert!(!ptr.is_null());
690            debug_assert_ne!(
691                glib::gobject_ffi::g_type_is_a((*ptr).type_, T::static_type().into_glib()),
692                glib::ffi::GFALSE
693            );
694            Borrowed::new(Self {
695                iter: ptr::NonNull::new_unchecked(ptr),
696                phantom: PhantomData,
697            })
698        }
699    }
700}
701
702#[doc(hidden)]
703impl<T: StaticType> glib::translate::FromGlibPtrFull<*mut ffi::GstIterator> for Iterator<T> {
704    #[inline]
705    unsafe fn from_glib_full(ptr: *mut ffi::GstIterator) -> Self {
706        unsafe {
707            debug_assert!(!ptr.is_null());
708            debug_assert_ne!(
709                glib::gobject_ffi::g_type_is_a((*ptr).type_, T::static_type().into_glib()),
710                glib::ffi::GFALSE
711            );
712            Self {
713                iter: ptr::NonNull::new_unchecked(ptr),
714                phantom: PhantomData,
715            }
716        }
717    }
718}
719
720#[must_use = "iterators are lazy and do nothing unless consumed"]
721pub struct StdIterator<T> {
722    inner: Iterator<T>,
723    error: Option<IteratorError>,
724}
725
726impl<T> StdIterator<T> {
727    fn new(inner: Iterator<T>) -> Self {
728        skip_assert_initialized!();
729        Self { inner, error: None }
730    }
731}
732
733impl<T: StaticType + 'static> Clone for StdIterator<T> {
734    #[inline]
735    fn clone(&self) -> Self {
736        Self {
737            inner: self.inner.clone(),
738            error: self.error,
739        }
740    }
741}
742
743impl<T> fmt::Debug for StdIterator<T> {
744    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
745        f.debug_struct("StdIterator")
746            .field("inner", &self.inner)
747            .field("error", &self.error)
748            .finish()
749    }
750}
751
752impl<T> iter::Iterator for StdIterator<T>
753where
754    for<'a> T: FromValue<'a> + 'static,
755{
756    type Item = Result<T, IteratorError>;
757
758    fn next(&mut self) -> Option<Self::Item> {
759        match self.error {
760            // Fuse the iterator after returning IteratorError::Error
761            Some(IteratorError::Error) => return None,
762
763            // The iterator needs a resync
764            Some(IteratorError::Resync) => self.inner.resync(),
765
766            None => {}
767        }
768
769        let res = self.inner.next();
770        self.error = res.as_ref().err().copied();
771        res.transpose()
772    }
773}
774
775impl<T> iter::FusedIterator for StdIterator<T> where for<'a> T: FromValue<'a> + 'static {}
776
777#[cfg(test)]
778mod tests {
779    use super::*;
780
781    #[test]
782    fn test_vec() {
783        crate::init().unwrap();
784
785        let vec = vec![1i32, 2, 3];
786        let mut it = Iterator::from_vec(vec);
787        let val = it.next();
788        assert_eq!(val, Ok(Some(1)));
789        let val = it.next();
790        assert_eq!(val, Ok(Some(2)));
791        let val = it.next();
792        assert_eq!(val, Ok(Some(3)));
793        assert_eq!(it.next(), Ok(None));
794
795        let vec = vec![1i32, 2, 3];
796        let mut it = Iterator::from_vec(vec);
797        let mut vals = Vec::new();
798        while let Ok(Some(res)) = it.next() {
799            vals.push(res);
800        }
801        assert_eq!(vals, [1, 2, 3]);
802    }
803
804    #[test]
805    fn test_filter() {
806        crate::init().unwrap();
807
808        let vec = vec![1i32, 2, 3];
809        let mut it = Iterator::from_vec(vec).filter(|val| val % 2 == 1);
810
811        let mut vals = Vec::new();
812        while let Ok(Some(res)) = it.next() {
813            vals.push(res);
814        }
815        assert_eq!(vals, [1, 3]);
816    }
817
818    #[test]
819    fn test_find() {
820        crate::init().unwrap();
821
822        // Our find
823        let vec = vec![1i32, 2, 3];
824        let val = Iterator::from_vec(vec).find(|val| val == 2);
825        assert_eq!(val.unwrap(), 2);
826    }
827
828    #[test]
829    fn test_foreach() {
830        crate::init().unwrap();
831
832        let vec = vec![1i32, 2, 3];
833        let mut sum = 0;
834        let res = Iterator::from_vec(vec).foreach(|val| sum += val);
835        assert_eq!(res, Ok(()));
836        assert_eq!(sum, 6);
837    }
838
839    #[test]
840    fn test_fold() {
841        crate::init().unwrap();
842
843        // Our fold
844        let vec = vec![1i32, 2, 3];
845        let res = Iterator::from_vec(vec).fold(0, |mut sum, val| {
846            sum += val;
847            Ok(sum)
848        });
849        assert_eq!(res.unwrap(), 6);
850    }
851
852    #[test]
853    fn test_std() {
854        crate::init().unwrap();
855
856        let mut it = Iterator::from_vec(vec![1i32, 2, 3]).into_iter();
857        assert_eq!(it.next(), Some(Ok(1)));
858        assert_eq!(it.next(), Some(Ok(2)));
859        assert_eq!(it.next(), Some(Ok(3)));
860        assert_eq!(it.next(), None);
861    }
862
863    #[test]
864    fn test_into_iter() {
865        crate::init().unwrap();
866
867        let mut v = vec![1i32, 2, 3].into_iter();
868        for x in Iterator::from_vec(vec![1i32, 2, 3]) {
869            assert_eq!(x.unwrap(), v.next().unwrap());
870        }
871        assert_eq!(v.next(), None);
872    }
873
874    #[test]
875    fn test_std_resync_collect() {
876        use std::collections::BTreeSet;
877
878        use crate::prelude::*;
879
880        crate::init().unwrap();
881
882        let bin = crate::Bin::new();
883        let id1 = crate::ElementFactory::make("identity").build().unwrap();
884        let id2 = crate::ElementFactory::make("identity").build().unwrap();
885
886        bin.add(&id1).unwrap();
887
888        let mut it = bin.iterate_elements().into_iter();
889        assert_eq!(it.next().unwrap().unwrap(), id1);
890
891        bin.add(&id2).unwrap();
892
893        let res = it.by_ref().collect::<Result<Vec<_>, _>>().unwrap_err();
894        assert_eq!(res, IteratorError::Resync);
895
896        let mut elems = BTreeSet::new();
897        elems.insert(id1);
898        elems.insert(id2);
899
900        let res = it.by_ref().collect::<Result<BTreeSet<_>, _>>().unwrap();
901        assert_eq!(res, elems);
902
903        let res = it.collect::<Result<Vec<_>, _>>().unwrap();
904        assert!(res.is_empty());
905    }
906
907    #[test]
908    fn test_std_resync_find() {
909        use crate::prelude::*;
910
911        crate::init().unwrap();
912
913        let bin = crate::Bin::new();
914        let id1 = crate::ElementFactory::make("identity").build().unwrap();
915        let id2 = crate::ElementFactory::make("identity").build().unwrap();
916
917        bin.add(&id1).unwrap();
918
919        let mut it = bin.iterate_elements().into_iter();
920        assert_eq!(it.next().unwrap().unwrap(), id1);
921
922        bin.add(&id2).unwrap();
923
924        let res = it.find(|x| x.as_ref() == Ok(&id1));
925        assert_eq!(res.unwrap().unwrap(), id1);
926    }
927}