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