1use 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
23pub 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 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 Some(IteratorError::Error) => return None,
739
740 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 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 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}