1use 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
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 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 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 Some(IteratorError::Error) => return None,
762
763 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 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 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}