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 crate::ffi; |
6 | use glib::{ |
7 | ffi::{gconstpointer, gpointer}, |
8 | prelude::*, |
9 | translate::*, |
10 | value::{FromValue, ToValue}, |
11 | Value, |
12 | }; |
13 | use thiserror::Error; |
14 | |
15 | #[derive (Clone, Copy, Debug, Eq, PartialEq, Hash, Error)] |
16 | pub enum IteratorError { |
17 | #[error("Resync" )] |
18 | Resync, |
19 | #[error("Error" )] |
20 | Error, |
21 | } |
22 | |
23 | // Implemented manually so that we can use generics for the item |
24 | pub struct Iterator<T> { |
25 | iter: ptr::NonNull<ffi::GstIterator>, |
26 | phantom: PhantomData<T>, |
27 | } |
28 | |
29 | impl<T> Iterator<T> |
30 | where |
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 | |
165 | impl<T> Iterator<T> |
166 | where |
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 | |
197 | impl<T> Iterator<T> |
198 | where |
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(imp: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(imp:ArrayIteratorImpl::new(items)) |
209 | } |
210 | |
211 | pub fn from_option(items: Option<T>) -> Self { |
212 | skip_assert_initialized!(); |
213 | Self::new(imp:OptionIteratorImpl::new(items)) |
214 | } |
215 | |
216 | pub fn from_single(item: T) -> Self { |
217 | skip_assert_initialized!(); |
218 | Self::new(imp:OptionIteratorImpl::new(items:Some(item))) |
219 | } |
220 | } |
221 | |
222 | impl<T: 'static> IntoGlibPtr<*mut ffi::GstIterator> for Iterator<T> { |
223 | #[inline ] |
224 | unsafe fn into_glib_ptr(self) -> *mut ffi::GstIterator { |
225 | let s: ManuallyDrop> = mem::ManuallyDrop::new(self); |
226 | let it: *const GstIterator = s.to_glib_none().0; |
227 | it as *mut _ |
228 | } |
229 | } |
230 | |
231 | #[repr (C)] |
232 | struct RsIterator<T, I: IteratorImpl<T>> |
233 | where |
234 | for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static, |
235 | { |
236 | iter: ffi::GstIterator, |
237 | imp: I, |
238 | phantom: PhantomData<T>, |
239 | } |
240 | |
241 | pub trait IteratorImpl<T>: Clone + Send + 'static |
242 | where |
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 | |
249 | unsafe 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: *const RsIterator = it as *const RsIterator<T, I>; |
256 | let copy: *mut RsIterator = copy as *mut RsIterator<T, I>; |
257 | |
258 | ptr::write(&mut (*copy).imp, (*it).imp.clone()); |
259 | } |
260 | |
261 | unsafe extern "C" fn rs_iterator_free<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator) |
262 | where |
263 | for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static, |
264 | { |
265 | let it: *mut RsIterator = it as *mut RsIterator<T, I>; |
266 | ptr::drop_in_place(&mut (*it).imp); |
267 | } |
268 | |
269 | unsafe 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 |
273 | where |
274 | for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static, |
275 | { |
276 | let it: *mut RsIterator = it as *mut RsIterator<T, I>; |
277 | match (*it).imp.next() { |
278 | Some(Ok(value: T)) => { |
279 | let value: Value = value.to_value(); |
280 | ptr::write(dst:result, src:value.into_raw()); |
281 | ffi::GST_ITERATOR_OK |
282 | } |
283 | None => ffi::GST_ITERATOR_DONE, |
284 | Some(Err(res: IteratorError)) => match res { |
285 | IteratorError::Resync => ffi::GST_ITERATOR_RESYNC, |
286 | IteratorError::Error => ffi::GST_ITERATOR_ERROR, |
287 | }, |
288 | } |
289 | } |
290 | |
291 | unsafe extern "C" fn rs_iterator_resync<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator) |
292 | where |
293 | for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static, |
294 | { |
295 | let it: *mut RsIterator = it as *mut RsIterator<T, I>; |
296 | (*it).imp.resync(); |
297 | } |
298 | |
299 | #[derive (Clone)] |
300 | struct ArrayIteratorImpl<A, T> { |
301 | pos: usize, |
302 | items: A, |
303 | phantom: PhantomData<T>, |
304 | } |
305 | |
306 | impl<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 | |
317 | impl<T, A> IteratorImpl<T> for ArrayIteratorImpl<A, T> |
318 | where |
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: &[T] = self.items.as_ref(); |
324 | if self.pos < items.len() { |
325 | let res: Result = 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)] |
339 | struct OptionIteratorImpl<T> { |
340 | finished: bool, |
341 | items: Option<T>, |
342 | } |
343 | |
344 | impl<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 | |
354 | impl<T> IteratorImpl<T> for OptionIteratorImpl<T> |
355 | where |
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: Option> = 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 | |
372 | unsafe impl<T> Send for Iterator<T> {} |
373 | unsafe impl<T> Sync for Iterator<T> {} |
374 | |
375 | unsafe extern "C" fn filter_trampoline< |
376 | T: for<'a> dynFromValue<'a> + StaticType + 'static, |
377 | F: Fn(T) -> bool + Send + Sync + 'static, |
378 | >( |
379 | value: gconstpointer, |
380 | func: gconstpointer, |
381 | ) -> i32 { |
382 | let value: *const GValue = value as *const glib::gobject_ffi::GValue; |
383 | |
384 | let func: *const GValue = func as *const glib::gobject_ffi::GValue; |
385 | let func: *mut c_void = glib::gobject_ffi::g_value_get_boxed(func); |
386 | let func: &&(dyn Any + Send + Sync + 'static) = &*(func as *const &(dyn Any + Send + Sync + 'static)); |
387 | let func: &F = func.downcast_ref::<F>().unwrap(); |
388 | |
389 | let value: &Value = &*(value as *const glib::Value); |
390 | let value: T = value.get::<T>().expect(msg:"Iterator filter_trampoline" ); |
391 | |
392 | if func(value) { |
393 | 0 |
394 | } else { |
395 | -1 |
396 | } |
397 | } |
398 | |
399 | unsafe extern "C" fn filter_boxed_ref(boxed: gpointer) -> gpointer { |
400 | let boxed: Arc> = Arc::from_raw(ptr:boxed as *const Box<dyn Any + Send + Sync + 'static>); |
401 | let copy: Arc> = Arc::clone(&boxed); |
402 | |
403 | // Forget it and keep it alive, we will still need it later |
404 | let _ = Arc::into_raw(this:boxed); |
405 | |
406 | Arc::into_raw(this:copy) as gpointer |
407 | } |
408 | |
409 | unsafe extern "C" fn filter_boxed_unref(boxed: gpointer) { |
410 | let _ = Arc::from_raw(ptr:boxed as *const Box<dyn Any + Send + Sync + 'static>); |
411 | } |
412 | |
413 | unsafe 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 | |
443 | unsafe extern "C" fn find_trampoline<T, F: FnMut(T) -> bool>( |
444 | value: gconstpointer, |
445 | func: gconstpointer, |
446 | ) -> i32 |
447 | where |
448 | for<'a> T: FromValue<'a> + 'static, |
449 | { |
450 | let value: *const GValue = value as *const glib::gobject_ffi::GValue; |
451 | |
452 | let func: *mut F = func as *mut F; |
453 | let value: &Value = &*(value as *const glib::Value); |
454 | let value: T = value.get::<T>().expect(msg:"Iterator find_trampoline" ); |
455 | |
456 | if (*func)(value) { |
457 | 0 |
458 | } else { |
459 | -1 |
460 | } |
461 | } |
462 | |
463 | unsafe 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: *mut F = func as *mut F; |
470 | let value: &Value = &*(value as *const glib::Value); |
471 | let value: T = value.get::<T>().expect(msg:"Iterator foreach_trampoline" ); |
472 | |
473 | (*func)(value); |
474 | } |
475 | |
476 | unsafe 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 |
481 | where |
482 | for<'a> T: FromValue<'a> + 'static, |
483 | { |
484 | let func: *mut F = func as *mut F; |
485 | let value: &Value = &*(value as *const glib::Value); |
486 | let value: T = value.get::<T>().expect(msg:"Iterator fold_trampoline" ); |
487 | |
488 | let accum: &mut Option = &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: U) => { |
492 | *accum = Some(next_accum); |
493 | glib::ffi::GTRUE |
494 | } |
495 | Err(next_accum: U) => { |
496 | *accum = Some(next_accum); |
497 | glib::ffi::GFALSE |
498 | } |
499 | } |
500 | } |
501 | |
502 | impl<T: StaticType + 'static> Clone for Iterator<T> { |
503 | #[inline ] |
504 | fn clone(&self) -> Self { |
505 | unsafe { from_glib_full(ptr:ffi::gst_iterator_copy(self.to_glib_none().0)) } |
506 | } |
507 | } |
508 | |
509 | impl<T> fmt::Debug for Iterator<T> { |
510 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
511 | f&mut DebugStruct<'_, '_>.debug_struct("Iterator" ) |
512 | .field(name:"iter" , &self.iter) |
513 | .finish() |
514 | } |
515 | } |
516 | |
517 | impl<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 | |
526 | impl<T> iter::IntoIterator for Iterator<T> |
527 | where |
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 | |
538 | impl<T> glib::types::StaticType for Iterator<T> { |
539 | #[inline ] |
540 | fn static_type() -> glib::types::Type { |
541 | unsafe { glib::translate::from_glib(val:ffi::gst_iterator_get_type()) } |
542 | } |
543 | } |
544 | |
545 | impl<T: StaticType + 'static> glib::value::ValueType for Iterator<T> { |
546 | type Type = Self; |
547 | } |
548 | |
549 | impl<T: StaticType + 'static> glib::value::ValueTypeOptional for Iterator<T> {} |
550 | |
551 | unsafe 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 | ptr:glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstIterator |
558 | ) |
559 | } |
560 | } |
561 | |
562 | impl<T: StaticType + 'static> glib::value::ToValue for Iterator<T> { |
563 | fn to_value(&self) -> glib::Value { |
564 | let mut value: 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 | |
579 | impl<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: 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 | v_boxed:s.to_glib_none().0 as *mut _, |
587 | ) |
588 | } |
589 | value |
590 | } |
591 | } |
592 | |
593 | impl<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: 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_boxed:v.into_glib_ptr() as *mut _, |
601 | ) |
602 | } |
603 | value |
604 | } |
605 | } |
606 | |
607 | #[doc (hidden)] |
608 | impl<T> glib::translate::GlibPtrDefault for Iterator<T> { |
609 | type GlibType = *mut ffi::GstIterator; |
610 | } |
611 | |
612 | #[doc (hidden)] |
613 | unsafe impl<T: StaticType + 'static> TransparentPtrType for Iterator<T> {} |
614 | |
615 | #[doc (hidden)] |
616 | impl<'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)] |
630 | impl<'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)] |
642 | impl<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(ptr:ffi::gst_iterator_copy(it:ptr)) |
650 | } |
651 | } |
652 | |
653 | #[doc (hidden)] |
654 | impl<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(ptr:ffi::gst_iterator_copy(it:ptr)) |
662 | } |
663 | } |
664 | |
665 | #[doc (hidden)] |
666 | impl<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)] |
682 | impl<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 | pub struct StdIterator<T> { |
698 | inner: Iterator<T>, |
699 | error: Option<IteratorError>, |
700 | } |
701 | |
702 | impl<T> StdIterator<T> { |
703 | fn new(inner: Iterator<T>) -> Self { |
704 | skip_assert_initialized!(); |
705 | Self { inner, error: None } |
706 | } |
707 | } |
708 | |
709 | impl<T: StaticType + 'static> Clone for StdIterator<T> { |
710 | #[inline ] |
711 | fn clone(&self) -> Self { |
712 | Self { |
713 | inner: self.inner.clone(), |
714 | error: self.error, |
715 | } |
716 | } |
717 | } |
718 | |
719 | impl<T> fmt::Debug for StdIterator<T> { |
720 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
721 | f&mut DebugStruct<'_, '_>.debug_struct("StdIterator" ) |
722 | .field("inner" , &self.inner) |
723 | .field(name:"error" , &self.error) |
724 | .finish() |
725 | } |
726 | } |
727 | |
728 | impl<T> iter::Iterator for StdIterator<T> |
729 | where |
730 | for<'a> T: FromValue<'a> + 'static, |
731 | { |
732 | type Item = Result<T, IteratorError>; |
733 | |
734 | fn next(&mut self) -> Option<Self::Item> { |
735 | match self.error { |
736 | // Fuse the iterator after returning IteratorError::Error |
737 | Some(IteratorError::Error) => return None, |
738 | |
739 | // The iterator needs a resync |
740 | Some(IteratorError::Resync) => self.inner.resync(), |
741 | |
742 | None => {} |
743 | } |
744 | |
745 | let res: Result = self.inner.next(); |
746 | self.error = res.as_ref().err().copied(); |
747 | res.transpose() |
748 | } |
749 | } |
750 | |
751 | impl<T> iter::FusedIterator for StdIterator<T> where for<'a> T: FromValue<'a> + 'static {} |
752 | |
753 | #[cfg (test)] |
754 | mod tests { |
755 | use super::*; |
756 | |
757 | #[test ] |
758 | fn test_vec() { |
759 | crate::init().unwrap(); |
760 | |
761 | let vec = vec![1i32, 2, 3]; |
762 | let mut it = Iterator::from_vec(vec); |
763 | let val = it.next(); |
764 | assert_eq!(val, Ok(Some(1))); |
765 | let val = it.next(); |
766 | assert_eq!(val, Ok(Some(2))); |
767 | let val = it.next(); |
768 | assert_eq!(val, Ok(Some(3))); |
769 | assert_eq!(it.next(), Ok(None)); |
770 | |
771 | let vec = vec![1i32, 2, 3]; |
772 | let mut it = Iterator::from_vec(vec); |
773 | let mut vals = Vec::new(); |
774 | while let Ok(Some(res)) = it.next() { |
775 | vals.push(res); |
776 | } |
777 | assert_eq!(vals, [1, 2, 3]); |
778 | } |
779 | |
780 | #[test ] |
781 | fn test_filter() { |
782 | crate::init().unwrap(); |
783 | |
784 | let vec = vec![1i32, 2, 3]; |
785 | let mut it = Iterator::from_vec(vec).filter(|val| val % 2 == 1); |
786 | |
787 | let mut vals = Vec::new(); |
788 | while let Ok(Some(res)) = it.next() { |
789 | vals.push(res); |
790 | } |
791 | assert_eq!(vals, [1, 3]); |
792 | } |
793 | |
794 | #[test ] |
795 | fn test_find() { |
796 | crate::init().unwrap(); |
797 | |
798 | // Our find |
799 | let vec = vec![1i32, 2, 3]; |
800 | let val = Iterator::from_vec(vec).find(|val| val == 2); |
801 | assert_eq!(val.unwrap(), 2); |
802 | } |
803 | |
804 | #[test ] |
805 | fn test_foreach() { |
806 | crate::init().unwrap(); |
807 | |
808 | let vec = vec![1i32, 2, 3]; |
809 | let mut sum = 0; |
810 | let res = Iterator::from_vec(vec).foreach(|val| sum += val); |
811 | assert_eq!(res, Ok(())); |
812 | assert_eq!(sum, 6); |
813 | } |
814 | |
815 | #[test ] |
816 | fn test_fold() { |
817 | crate::init().unwrap(); |
818 | |
819 | // Our fold |
820 | let vec = vec![1i32, 2, 3]; |
821 | let res = Iterator::from_vec(vec).fold(0, |mut sum, val| { |
822 | sum += val; |
823 | Ok(sum) |
824 | }); |
825 | assert_eq!(res.unwrap(), 6); |
826 | } |
827 | |
828 | #[test ] |
829 | fn test_std() { |
830 | crate::init().unwrap(); |
831 | |
832 | let mut it = Iterator::from_vec(vec![1i32, 2, 3]).into_iter(); |
833 | assert_eq!(it.next(), Some(Ok(1))); |
834 | assert_eq!(it.next(), Some(Ok(2))); |
835 | assert_eq!(it.next(), Some(Ok(3))); |
836 | assert_eq!(it.next(), None); |
837 | } |
838 | |
839 | #[test ] |
840 | fn test_into_iter() { |
841 | crate::init().unwrap(); |
842 | |
843 | let mut v = vec![1i32, 2, 3].into_iter(); |
844 | for x in Iterator::from_vec(vec![1i32, 2, 3]) { |
845 | assert_eq!(x.unwrap(), v.next().unwrap()); |
846 | } |
847 | assert_eq!(v.next(), None); |
848 | } |
849 | |
850 | #[test ] |
851 | fn test_std_resync_collect() { |
852 | use std::collections::BTreeSet; |
853 | |
854 | use crate::prelude::*; |
855 | |
856 | crate::init().unwrap(); |
857 | |
858 | let bin = crate::Bin::new(); |
859 | let id1 = crate::ElementFactory::make("identity" ).build().unwrap(); |
860 | let id2 = crate::ElementFactory::make("identity" ).build().unwrap(); |
861 | |
862 | bin.add(&id1).unwrap(); |
863 | |
864 | let mut it = bin.iterate_elements().into_iter(); |
865 | assert_eq!(it.next().unwrap().unwrap(), id1); |
866 | |
867 | bin.add(&id2).unwrap(); |
868 | |
869 | let res = it.by_ref().collect::<Result<Vec<_>, _>>().unwrap_err(); |
870 | assert_eq!(res, IteratorError::Resync); |
871 | |
872 | let mut elems = BTreeSet::new(); |
873 | elems.insert(id1); |
874 | elems.insert(id2); |
875 | |
876 | let res = it.by_ref().collect::<Result<BTreeSet<_>, _>>().unwrap(); |
877 | assert_eq!(res, elems); |
878 | |
879 | let res = it.collect::<Result<Vec<_>, _>>().unwrap(); |
880 | assert!(res.is_empty()); |
881 | } |
882 | |
883 | #[test ] |
884 | fn test_std_resync_find() { |
885 | use crate::prelude::*; |
886 | |
887 | crate::init().unwrap(); |
888 | |
889 | let bin = crate::Bin::new(); |
890 | let id1 = crate::ElementFactory::make("identity" ).build().unwrap(); |
891 | let id2 = crate::ElementFactory::make("identity" ).build().unwrap(); |
892 | |
893 | bin.add(&id1).unwrap(); |
894 | |
895 | let mut it = bin.iterate_elements().into_iter(); |
896 | assert_eq!(it.next().unwrap().unwrap(), id1); |
897 | |
898 | bin.add(&id2).unwrap(); |
899 | |
900 | let res = it.find(|x| x.as_ref() == Ok(&id1)); |
901 | assert_eq!(res.unwrap().unwrap(), id1); |
902 | } |
903 | } |
904 | |