1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{any::Any, fmt, iter, marker::PhantomData, mem, ptr, sync::Arc}; |
4 | |
5 | use glib::{ |
6 | ffi::{gconstpointer, gpointer}, |
7 | translate::*, |
8 | value::{FromValue, ToValue}, |
9 | StaticType, Value, |
10 | }; |
11 | use thiserror::Error; |
12 | |
13 | #[derive (Clone, Copy, Debug, Eq, PartialEq, Hash, Error)] |
14 | pub 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 |
22 | pub struct Iterator<T> { |
23 | iter: ptr::NonNull<ffi::GstIterator>, |
24 | phantom: PhantomData<T>, |
25 | } |
26 | |
27 | impl<T> Iterator<T> |
28 | where |
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 | |
163 | impl<T> Iterator<T> |
164 | where |
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 | |
195 | impl<T> Iterator<T> |
196 | where |
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 | |
205 | impl<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)] |
215 | struct RsIterator<T, I: IteratorImpl<T>> |
216 | where |
217 | for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static, |
218 | { |
219 | iter: ffi::GstIterator, |
220 | imp: I, |
221 | phantom: PhantomData<T>, |
222 | } |
223 | |
224 | pub trait IteratorImpl<T>: Clone + Send + 'static |
225 | where |
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 | |
232 | unsafe 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 | |
244 | unsafe extern "C" fn rs_iterator_free<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator) |
245 | where |
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 | |
252 | unsafe 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 |
256 | where |
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 | |
274 | unsafe extern "C" fn rs_iterator_resync<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator) |
275 | where |
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)] |
283 | struct VecIteratorImpl<T> { |
284 | pos: usize, |
285 | items: Vec<T>, |
286 | } |
287 | |
288 | impl<T> VecIteratorImpl<T> |
289 | where |
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 | |
298 | impl<T> IteratorImpl<T> for VecIteratorImpl<T> |
299 | where |
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 | |
317 | unsafe impl<T> Send for Iterator<T> {} |
318 | unsafe impl<T> Sync for Iterator<T> {} |
319 | |
320 | unsafe extern "C" fn filter_trampoline<T: StaticType, F: Fn(T) -> bool + Send + Sync + 'static>( |
321 | value: gconstpointer, |
322 | func: gconstpointer, |
323 | ) -> i32 |
324 | where |
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 | |
344 | unsafe 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 | |
354 | unsafe 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 | |
358 | unsafe 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 | |
391 | unsafe extern "C" fn find_trampoline<T, F: FnMut(T) -> bool>( |
392 | value: gconstpointer, |
393 | func: gconstpointer, |
394 | ) -> i32 |
395 | where |
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 | |
411 | unsafe 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 | |
424 | unsafe 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 |
429 | where |
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 | |
450 | impl<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 | |
457 | impl<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 | |
465 | impl<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 | |
474 | impl<T> iter::IntoIterator for Iterator<T> |
475 | where |
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 | |
486 | impl<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 | |
493 | impl<T: StaticType + 'static> glib::value::ValueType for Iterator<T> { |
494 | type Type = Self; |
495 | } |
496 | |
497 | impl<T: StaticType + 'static> glib::value::ValueTypeOptional for Iterator<T> {} |
498 | |
499 | unsafe 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 | |
510 | impl<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 | |
527 | impl<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 | |
541 | impl<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)] |
556 | impl<T> glib::translate::GlibPtrDefault for Iterator<T> { |
557 | type GlibType = *mut ffi::GstIterator; |
558 | } |
559 | |
560 | #[doc (hidden)] |
561 | unsafe impl<T: StaticType + 'static> TransparentPtrType for Iterator<T> {} |
562 | |
563 | #[doc (hidden)] |
564 | impl<'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)] |
578 | impl<'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)] |
590 | impl<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)] |
602 | impl<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)] |
614 | impl<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)] |
630 | impl<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 | |
645 | pub struct StdIterator<T> { |
646 | inner: Iterator<T>, |
647 | error: Option<IteratorError>, |
648 | } |
649 | |
650 | impl<T> StdIterator<T> { |
651 | fn new(inner: Iterator<T>) -> Self { |
652 | skip_assert_initialized!(); |
653 | Self { inner, error: None } |
654 | } |
655 | } |
656 | |
657 | impl<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 | |
667 | impl<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 | |
676 | impl<T> iter::Iterator for StdIterator<T> |
677 | where |
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 = self.inner.next(); |
694 | self.error = res.as_ref().err().copied(); |
695 | res.transpose() |
696 | } |
697 | } |
698 | |
699 | impl<T> iter::FusedIterator for StdIterator<T> where for<'a> T: FromValue<'a> + 'static {} |
700 | |
701 | #[cfg (test)] |
702 | mod 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 | |