1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{ |
4 | borrow::{Borrow, BorrowMut, ToOwned}, |
5 | fmt, |
6 | marker::PhantomData, |
7 | mem, |
8 | ops::{Deref, DerefMut}, |
9 | ptr, str, |
10 | }; |
11 | |
12 | use crate::ffi; |
13 | use glib::{prelude::*, translate::*}; |
14 | use once_cell::sync::Lazy; |
15 | |
16 | #[doc (alias = "GstCapsFeatures" )] |
17 | #[repr (transparent)] |
18 | pub struct CapsFeatures(ptr::NonNull<ffi::GstCapsFeatures>); |
19 | unsafe impl Send for CapsFeatures {} |
20 | unsafe impl Sync for CapsFeatures {} |
21 | |
22 | impl CapsFeatures { |
23 | #[doc (alias = "gst_caps_features_new" )] |
24 | pub fn new(features: impl IntoIterator<Item = impl IntoGStr>) -> Self { |
25 | skip_assert_initialized!(); |
26 | let mut f = Self::new_empty(); |
27 | |
28 | for feature in features { |
29 | f.add(feature); |
30 | } |
31 | |
32 | f |
33 | } |
34 | |
35 | #[doc (alias = "gst_caps_features_new_id" )] |
36 | pub fn from_quarks(features: impl IntoIterator<Item = glib::Quark>) -> Self { |
37 | skip_assert_initialized!(); |
38 | let mut f = Self::new_empty(); |
39 | |
40 | for feature in features.into_iter() { |
41 | f.add_from_quark(feature); |
42 | } |
43 | |
44 | f |
45 | } |
46 | |
47 | #[doc (alias = "gst_caps_features_new_empty" )] |
48 | pub fn new_empty() -> Self { |
49 | assert_initialized_main_thread!(); |
50 | unsafe { |
51 | CapsFeatures(ptr::NonNull::new_unchecked( |
52 | ffi::gst_caps_features_new_empty(), |
53 | )) |
54 | } |
55 | } |
56 | |
57 | #[doc (alias = "gst_caps_features_new_any" )] |
58 | pub fn new_any() -> Self { |
59 | assert_initialized_main_thread!(); |
60 | unsafe { CapsFeatures(ptr::NonNull::new_unchecked(ffi::gst_caps_features_new_any())) } |
61 | } |
62 | } |
63 | |
64 | impl IntoGlibPtr<*mut ffi::GstCapsFeatures> for CapsFeatures { |
65 | #[inline ] |
66 | unsafe fn into_glib_ptr(self) -> *mut ffi::GstCapsFeatures { |
67 | let s: ManuallyDrop = mem::ManuallyDrop::new(self); |
68 | s.0.as_ptr() |
69 | } |
70 | } |
71 | |
72 | impl Deref for CapsFeatures { |
73 | type Target = CapsFeaturesRef; |
74 | |
75 | #[inline ] |
76 | fn deref(&self) -> &CapsFeaturesRef { |
77 | unsafe { &*(self.0.as_ref() as *const ffi::GstCapsFeatures as *const CapsFeaturesRef) } |
78 | } |
79 | } |
80 | |
81 | impl DerefMut for CapsFeatures { |
82 | #[inline ] |
83 | fn deref_mut(&mut self) -> &mut CapsFeaturesRef { |
84 | unsafe { &mut *(self.0.as_mut() as *mut ffi::GstCapsFeatures as *mut CapsFeaturesRef) } |
85 | } |
86 | } |
87 | |
88 | impl AsRef<CapsFeaturesRef> for CapsFeatures { |
89 | #[inline ] |
90 | fn as_ref(&self) -> &CapsFeaturesRef { |
91 | self.deref() |
92 | } |
93 | } |
94 | |
95 | impl AsMut<CapsFeaturesRef> for CapsFeatures { |
96 | #[inline ] |
97 | fn as_mut(&mut self) -> &mut CapsFeaturesRef { |
98 | self.deref_mut() |
99 | } |
100 | } |
101 | |
102 | impl Clone for CapsFeatures { |
103 | #[inline ] |
104 | fn clone(&self) -> Self { |
105 | unsafe { |
106 | let ptr: *mut GstCapsFeatures = ffi::gst_caps_features_copy(self.0.as_ref()); |
107 | debug_assert!(!ptr.is_null()); |
108 | CapsFeatures(ptr::NonNull::new_unchecked(ptr)) |
109 | } |
110 | } |
111 | } |
112 | |
113 | impl Drop for CapsFeatures { |
114 | #[inline ] |
115 | fn drop(&mut self) { |
116 | unsafe { ffi::gst_caps_features_free(self.0.as_mut()) } |
117 | } |
118 | } |
119 | |
120 | impl fmt::Debug for CapsFeatures { |
121 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
122 | f&mut DebugTuple<'_, '_>.debug_tuple(name:"CapsFeatures" ) |
123 | .field(&self.to_string()) |
124 | .finish() |
125 | } |
126 | } |
127 | |
128 | impl fmt::Display for CapsFeatures { |
129 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
130 | // Need to make sure to not call ToString::to_string() here, which |
131 | // we have because of the Display impl. We need CapsFeaturesRef::to_string() |
132 | f.write_str(&CapsFeaturesRef::to_string(self.as_ref())) |
133 | } |
134 | } |
135 | |
136 | impl str::FromStr for CapsFeatures { |
137 | type Err = glib::BoolError; |
138 | |
139 | #[doc (alias = "gst_caps_features_from_string" )] |
140 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
141 | assert_initialized_main_thread!(); |
142 | unsafe { |
143 | let ptr: *mut GstCapsFeatures = s.run_with_gstr(|s: &GStr| ffi::gst_caps_features_from_string(features:s.as_ptr())); |
144 | if ptr.is_null() { |
145 | return Err(glib::bool_error!( |
146 | "Failed to parse caps features from string" |
147 | )); |
148 | } |
149 | |
150 | Ok(Self(ptr::NonNull::new_unchecked(ptr))) |
151 | } |
152 | } |
153 | } |
154 | |
155 | impl Borrow<CapsFeaturesRef> for CapsFeatures { |
156 | #[inline ] |
157 | fn borrow(&self) -> &CapsFeaturesRef { |
158 | self.as_ref() |
159 | } |
160 | } |
161 | |
162 | impl BorrowMut<CapsFeaturesRef> for CapsFeatures { |
163 | #[inline ] |
164 | fn borrow_mut(&mut self) -> &mut CapsFeaturesRef { |
165 | self.as_mut() |
166 | } |
167 | } |
168 | |
169 | impl glib::types::StaticType for CapsFeatures { |
170 | #[inline ] |
171 | fn static_type() -> glib::types::Type { |
172 | unsafe { from_glib(val:ffi::gst_caps_features_get_type()) } |
173 | } |
174 | } |
175 | |
176 | impl<'a> ToGlibPtr<'a, *const ffi::GstCapsFeatures> for CapsFeatures { |
177 | type Storage = PhantomData<&'a Self>; |
178 | |
179 | #[inline ] |
180 | fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstCapsFeatures, Self> { |
181 | unsafe { Stash(self.0.as_ref(), PhantomData) } |
182 | } |
183 | |
184 | #[inline ] |
185 | fn to_glib_full(&self) -> *const ffi::GstCapsFeatures { |
186 | unsafe { ffi::gst_caps_features_copy(self.0.as_ref()) } |
187 | } |
188 | } |
189 | |
190 | impl<'a> ToGlibPtr<'a, *mut ffi::GstCapsFeatures> for CapsFeatures { |
191 | type Storage = PhantomData<&'a Self>; |
192 | |
193 | #[inline ] |
194 | fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GstCapsFeatures, Self> { |
195 | unsafe { |
196 | Stash( |
197 | self.0.as_ref() as *const ffi::GstCapsFeatures as *mut ffi::GstCapsFeatures, |
198 | PhantomData, |
199 | ) |
200 | } |
201 | } |
202 | |
203 | #[inline ] |
204 | fn to_glib_full(&self) -> *mut ffi::GstCapsFeatures { |
205 | unsafe { ffi::gst_caps_features_copy(self.0.as_ref()) } |
206 | } |
207 | } |
208 | |
209 | impl<'a> ToGlibPtrMut<'a, *mut ffi::GstCapsFeatures> for CapsFeatures { |
210 | type Storage = PhantomData<&'a mut Self>; |
211 | |
212 | #[inline ] |
213 | fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GstCapsFeatures, Self> { |
214 | unsafe { StashMut(self.0.as_mut(), PhantomData) } |
215 | } |
216 | } |
217 | |
218 | impl FromGlibPtrNone<*const ffi::GstCapsFeatures> for CapsFeatures { |
219 | #[inline ] |
220 | unsafe fn from_glib_none(ptr: *const ffi::GstCapsFeatures) -> Self { |
221 | debug_assert!(!ptr.is_null()); |
222 | let ptr: *mut GstCapsFeatures = ffi::gst_caps_features_copy(features:ptr); |
223 | debug_assert!(!ptr.is_null()); |
224 | CapsFeatures(ptr::NonNull::new_unchecked(ptr)) |
225 | } |
226 | } |
227 | |
228 | impl FromGlibPtrNone<*mut ffi::GstCapsFeatures> for CapsFeatures { |
229 | #[inline ] |
230 | unsafe fn from_glib_none(ptr: *mut ffi::GstCapsFeatures) -> Self { |
231 | debug_assert!(!ptr.is_null()); |
232 | let ptr: *mut GstCapsFeatures = ffi::gst_caps_features_copy(features:ptr); |
233 | debug_assert!(!ptr.is_null()); |
234 | CapsFeatures(ptr::NonNull::new_unchecked(ptr)) |
235 | } |
236 | } |
237 | |
238 | impl FromGlibPtrFull<*const ffi::GstCapsFeatures> for CapsFeatures { |
239 | #[inline ] |
240 | unsafe fn from_glib_full(ptr: *const ffi::GstCapsFeatures) -> Self { |
241 | debug_assert!(!ptr.is_null()); |
242 | CapsFeatures(ptr::NonNull::new_unchecked( |
243 | ptr as *mut ffi::GstCapsFeatures, |
244 | )) |
245 | } |
246 | } |
247 | |
248 | impl FromGlibPtrFull<*mut ffi::GstCapsFeatures> for CapsFeatures { |
249 | #[inline ] |
250 | unsafe fn from_glib_full(ptr: *mut ffi::GstCapsFeatures) -> Self { |
251 | debug_assert!(!ptr.is_null()); |
252 | CapsFeatures(ptr::NonNull::new_unchecked(ptr)) |
253 | } |
254 | } |
255 | |
256 | impl glib::value::ValueType for CapsFeatures { |
257 | type Type = Self; |
258 | } |
259 | |
260 | impl glib::value::ValueTypeOptional for CapsFeatures {} |
261 | |
262 | unsafe impl<'a> glib::value::FromValue<'a> for CapsFeatures { |
263 | type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>; |
264 | |
265 | unsafe fn from_value(value: &'a glib::Value) -> Self { |
266 | skip_assert_initialized!(); |
267 | from_glib_none(ptr:glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) |
268 | as *mut ffi::GstCapsFeatures) |
269 | } |
270 | } |
271 | |
272 | impl glib::value::ToValue for CapsFeatures { |
273 | fn to_value(&self) -> glib::Value { |
274 | let mut value: Value = glib::Value::for_value_type::<Self>(); |
275 | unsafe { |
276 | glib::gobject_ffi::g_value_set_boxed( |
277 | value.to_glib_none_mut().0, |
278 | v_boxed:ToGlibPtr::<*mut ffi::GstCapsFeatures>::to_glib_none(self).0 as *mut _, |
279 | ) |
280 | } |
281 | value |
282 | } |
283 | |
284 | fn value_type(&self) -> glib::Type { |
285 | Self::static_type() |
286 | } |
287 | } |
288 | |
289 | impl glib::value::ToValueOptional for CapsFeatures { |
290 | fn to_value_optional(s: Option<&Self>) -> glib::Value { |
291 | skip_assert_initialized!(); |
292 | let mut value: Value = glib::Value::for_value_type::<Self>(); |
293 | unsafe { |
294 | glib::gobject_ffi::g_value_set_boxed( |
295 | value.to_glib_none_mut().0, |
296 | v_boxed:ToGlibPtr::<*mut ffi::GstCapsFeatures>::to_glib_none(&s).0 as *mut _, |
297 | ) |
298 | } |
299 | value |
300 | } |
301 | } |
302 | |
303 | impl From<CapsFeatures> for glib::Value { |
304 | fn from(v: CapsFeatures) -> glib::Value { |
305 | skip_assert_initialized!(); |
306 | let mut value: Value = glib::Value::for_value_type::<CapsFeatures>(); |
307 | unsafe { |
308 | glib::gobject_ffi::g_value_take_boxed( |
309 | value.to_glib_none_mut().0, |
310 | v_boxed:IntoGlibPtr::<*mut ffi::GstCapsFeatures>::into_glib_ptr(self:v) as *mut _, |
311 | ) |
312 | } |
313 | value |
314 | } |
315 | } |
316 | |
317 | impl GlibPtrDefault for CapsFeatures { |
318 | type GlibType = *mut ffi::GstCapsFeatures; |
319 | } |
320 | |
321 | unsafe impl TransparentPtrType for CapsFeatures {} |
322 | |
323 | #[repr (transparent)] |
324 | #[doc (alias = "GstCapsFeatures" )] |
325 | pub struct CapsFeaturesRef(ffi::GstCapsFeatures); |
326 | |
327 | impl CapsFeaturesRef { |
328 | #[inline ] |
329 | pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstCapsFeatures) -> &'a CapsFeaturesRef { |
330 | debug_assert!(!ptr.is_null()); |
331 | |
332 | &*(ptr as *mut CapsFeaturesRef) |
333 | } |
334 | |
335 | #[inline ] |
336 | pub unsafe fn from_glib_borrow_mut<'a>( |
337 | ptr: *mut ffi::GstCapsFeatures, |
338 | ) -> &'a mut CapsFeaturesRef { |
339 | debug_assert!(!ptr.is_null()); |
340 | |
341 | &mut *(ptr as *mut CapsFeaturesRef) |
342 | } |
343 | |
344 | #[inline ] |
345 | pub fn as_ptr(&self) -> *const ffi::GstCapsFeatures { |
346 | self as *const Self as *const ffi::GstCapsFeatures |
347 | } |
348 | |
349 | #[inline ] |
350 | pub fn as_mut_ptr(&self) -> *mut ffi::GstCapsFeatures { |
351 | self as *const Self as *mut ffi::GstCapsFeatures |
352 | } |
353 | |
354 | pub fn is_empty(&self) -> bool { |
355 | self.size() == 0 && !self.is_any() |
356 | } |
357 | |
358 | #[doc (alias = "gst_caps_features_is_any" )] |
359 | pub fn is_any(&self) -> bool { |
360 | unsafe { from_glib(ffi::gst_caps_features_is_any(self.as_ptr())) } |
361 | } |
362 | |
363 | #[doc (alias = "gst_caps_features_contains" )] |
364 | pub fn contains(&self, feature: impl IntoGStr) -> bool { |
365 | unsafe { |
366 | feature.run_with_gstr(|feature| { |
367 | from_glib(ffi::gst_caps_features_contains( |
368 | self.as_ptr(), |
369 | feature.as_ptr(), |
370 | )) |
371 | }) |
372 | } |
373 | } |
374 | |
375 | #[doc (alias = "gst_caps_features_contains_id" )] |
376 | pub fn contains_quark(&self, feature: glib::Quark) -> bool { |
377 | unsafe { |
378 | from_glib(ffi::gst_caps_features_contains_id( |
379 | self.as_ptr(), |
380 | feature.into_glib(), |
381 | )) |
382 | } |
383 | } |
384 | |
385 | #[doc (alias = "get_size" )] |
386 | #[doc (alias = "gst_caps_features_get_size" )] |
387 | pub fn size(&self) -> usize { |
388 | unsafe { ffi::gst_caps_features_get_size(self.as_ptr()) as usize } |
389 | } |
390 | |
391 | #[doc (alias = "get_nth" )] |
392 | #[doc (alias = "gst_caps_features_get_nth" )] |
393 | pub fn nth(&self, idx: usize) -> Option<&glib::GStr> { |
394 | if idx >= self.size() { |
395 | return None; |
396 | } |
397 | |
398 | unsafe { |
399 | let feature = ffi::gst_caps_features_get_nth(self.as_ptr(), idx as u32); |
400 | if feature.is_null() { |
401 | return None; |
402 | } |
403 | |
404 | // Safety: we can return a GStr based on the feature here because |
405 | // the lifetime of the returned value is constrained by &self. |
406 | Some(glib::GStr::from_ptr(feature)) |
407 | } |
408 | } |
409 | |
410 | #[doc (alias = "gst_caps_features_get_nth_id" )] |
411 | pub fn nth_quark(&self, idx: usize) -> Option<glib::Quark> { |
412 | if idx >= self.size() { |
413 | return None; |
414 | } |
415 | |
416 | unsafe { |
417 | let feature = ffi::gst_caps_features_get_nth_id(self.as_ptr(), idx as u32); |
418 | Some(from_glib(feature)) |
419 | } |
420 | } |
421 | |
422 | #[doc (alias = "gst_caps_features_add" )] |
423 | pub fn add(&mut self, feature: impl IntoGStr) { |
424 | unsafe { |
425 | feature.run_with_gstr(|feature| { |
426 | ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ptr()) |
427 | }) |
428 | } |
429 | } |
430 | |
431 | #[doc (alias = "gst_caps_features_remove" )] |
432 | pub fn remove(&mut self, feature: impl IntoGStr) { |
433 | unsafe { |
434 | feature.run_with_gstr(|feature| { |
435 | ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.as_ptr()) |
436 | }) |
437 | } |
438 | } |
439 | |
440 | #[doc (alias = "gst_caps_features_add_id" )] |
441 | pub fn add_from_quark(&mut self, feature: glib::Quark) { |
442 | unsafe { ffi::gst_caps_features_add_id(self.as_mut_ptr(), feature.into_glib()) } |
443 | } |
444 | |
445 | #[doc (alias = "gst_caps_features_remove_id" )] |
446 | pub fn remove_by_quark(&mut self, feature: glib::Quark) { |
447 | unsafe { ffi::gst_caps_features_remove_id(self.as_mut_ptr(), feature.into_glib()) } |
448 | } |
449 | |
450 | pub fn iter(&self) -> Iter { |
451 | Iter::new(self) |
452 | } |
453 | |
454 | // This is not an equivalence relation with regards to ANY. Everything is equal to ANY |
455 | #[doc (alias = "gst_caps_features_is_equal" )] |
456 | pub fn is_equal(&self, other: &CapsFeaturesRef) -> bool { |
457 | unsafe { |
458 | from_glib(ffi::gst_caps_features_is_equal( |
459 | self.as_ptr(), |
460 | other.as_ptr(), |
461 | )) |
462 | } |
463 | } |
464 | } |
465 | |
466 | impl glib::types::StaticType for CapsFeaturesRef { |
467 | #[inline ] |
468 | fn static_type() -> glib::types::Type { |
469 | unsafe { from_glib(val:ffi::gst_structure_get_type()) } |
470 | } |
471 | } |
472 | |
473 | impl<'a> std::iter::Extend<&'a str> for CapsFeaturesRef { |
474 | fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) { |
475 | iter.into_iter().for_each(|f: &'a str| self.add(feature:f)); |
476 | } |
477 | } |
478 | |
479 | impl<'a> std::iter::Extend<&'a glib::GStr> for CapsFeaturesRef { |
480 | fn extend<T: IntoIterator<Item = &'a glib::GStr>>(&mut self, iter: T) { |
481 | iter.into_iter().for_each(|f: &'a GStr| self.add(feature:f)); |
482 | } |
483 | } |
484 | |
485 | impl std::iter::Extend<String> for CapsFeaturesRef { |
486 | fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) { |
487 | iter.into_iter().for_each(|f: String| self.add(&f)); |
488 | } |
489 | } |
490 | |
491 | impl std::iter::Extend<glib::GString> for CapsFeaturesRef { |
492 | fn extend<T: IntoIterator<Item = glib::GString>>(&mut self, iter: T) { |
493 | iter.into_iter().for_each(|f: GString| self.add(&f)); |
494 | } |
495 | } |
496 | |
497 | impl std::iter::Extend<glib::Quark> for CapsFeaturesRef { |
498 | fn extend<T: IntoIterator<Item = glib::Quark>>(&mut self, iter: T) { |
499 | iter.into_iter().for_each(|f: Quark| self.add_from_quark(feature:f)); |
500 | } |
501 | } |
502 | |
503 | unsafe impl<'a> glib::value::FromValue<'a> for &'a CapsFeaturesRef { |
504 | type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>; |
505 | |
506 | unsafe fn from_value(value: &'a glib::Value) -> Self { |
507 | skip_assert_initialized!(); |
508 | &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const CapsFeaturesRef) |
509 | } |
510 | } |
511 | |
512 | impl glib::value::ToValue for CapsFeaturesRef { |
513 | fn to_value(&self) -> glib::Value { |
514 | let mut value: Value = glib::Value::for_value_type::<CapsFeatures>(); |
515 | unsafe { |
516 | glib::gobject_ffi::g_value_set_boxed( |
517 | value.to_glib_none_mut().0, |
518 | self.as_mut_ptr() as *mut _, |
519 | ) |
520 | } |
521 | value |
522 | } |
523 | |
524 | fn value_type(&self) -> glib::Type { |
525 | Self::static_type() |
526 | } |
527 | } |
528 | |
529 | impl glib::value::ToValueOptional for CapsFeaturesRef { |
530 | fn to_value_optional(s: Option<&Self>) -> glib::Value { |
531 | skip_assert_initialized!(); |
532 | let mut value: Value = glib::Value::for_value_type::<CapsFeatures>(); |
533 | unsafe { |
534 | glib::gobject_ffi::g_value_set_boxed( |
535 | value.to_glib_none_mut().0, |
536 | v_boxed:s.map(|s| s.as_mut_ptr()).unwrap_or(default:ptr::null_mut()) as *mut _, |
537 | ) |
538 | } |
539 | value |
540 | } |
541 | } |
542 | |
543 | #[derive (Debug)] |
544 | pub struct Iter<'a> { |
545 | caps_features: &'a CapsFeaturesRef, |
546 | idx: usize, |
547 | n_features: usize, |
548 | } |
549 | |
550 | impl<'a> Iter<'a> { |
551 | fn new(caps_features: &'a CapsFeaturesRef) -> Iter<'a> { |
552 | skip_assert_initialized!(); |
553 | let n_features: usize = caps_features.size(); |
554 | |
555 | Iter { |
556 | caps_features, |
557 | idx: 0, |
558 | n_features, |
559 | } |
560 | } |
561 | } |
562 | |
563 | impl<'a> Iterator for Iter<'a> { |
564 | type Item = &'a glib::GStr; |
565 | |
566 | fn next(&mut self) -> Option<Self::Item> { |
567 | if self.idx >= self.n_features { |
568 | return None; |
569 | } |
570 | |
571 | unsafe { |
572 | let feature = |
573 | ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.idx as u32); |
574 | debug_assert!(!feature.is_null()); |
575 | |
576 | self.idx += 1; |
577 | |
578 | // Safety: we can return a GStr based on the feature here because the lifetime |
579 | // of the returned Item is constrained by the underlying CapsFeatureRef. |
580 | Some(glib::GStr::from_ptr(feature)) |
581 | } |
582 | } |
583 | |
584 | fn size_hint(&self) -> (usize, Option<usize>) { |
585 | let remaining = self.n_features - self.idx; |
586 | |
587 | (remaining, Some(remaining)) |
588 | } |
589 | |
590 | fn count(self) -> usize { |
591 | self.n_features - self.idx |
592 | } |
593 | |
594 | // checker-ignore-item |
595 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
596 | let (end, overflow) = self.idx.overflowing_add(n); |
597 | if end >= self.n_features || overflow { |
598 | self.idx = self.n_features; |
599 | None |
600 | } else { |
601 | unsafe { |
602 | self.idx = end + 1; |
603 | let feature = |
604 | ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), end as u32); |
605 | debug_assert!(!feature.is_null()); |
606 | |
607 | // Safety: we can return a GStr based on the feature here because the lifetime |
608 | // of the returned Item is constrained by the underlying CapsFeatureRef. |
609 | Some(glib::GStr::from_ptr(feature)) |
610 | } |
611 | } |
612 | } |
613 | |
614 | fn last(self) -> Option<Self::Item> { |
615 | if self.idx == self.n_features { |
616 | None |
617 | } else { |
618 | unsafe { |
619 | let feature = ffi::gst_caps_features_get_nth( |
620 | self.caps_features.as_ptr(), |
621 | self.n_features as u32 - 1, |
622 | ); |
623 | debug_assert!(!feature.is_null()); |
624 | |
625 | // Safety: we can return a GStr based on the feature here because the lifetime |
626 | // of the returned Item is constrained by the underlying CapsFeatureRef. |
627 | Some(glib::GStr::from_ptr(feature)) |
628 | } |
629 | } |
630 | } |
631 | } |
632 | |
633 | impl DoubleEndedIterator for Iter<'_> { |
634 | fn next_back(&mut self) -> Option<Self::Item> { |
635 | if self.idx == self.n_features { |
636 | return None; |
637 | } |
638 | |
639 | self.n_features -= 1; |
640 | |
641 | unsafe { |
642 | let feature = |
643 | ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.n_features as u32); |
644 | debug_assert!(!feature.is_null()); |
645 | |
646 | // Safety: we can return a GStr based on the feature here because the lifetime |
647 | // of the returned Item is constrained by the underlying CapsFeatureRef. |
648 | Some(glib::GStr::from_ptr(feature)) |
649 | } |
650 | } |
651 | |
652 | fn nth_back(&mut self, n: usize) -> Option<Self::Item> { |
653 | let (end, overflow) = self.n_features.overflowing_sub(n); |
654 | if end <= self.idx || overflow { |
655 | self.idx = self.n_features; |
656 | None |
657 | } else { |
658 | unsafe { |
659 | self.n_features = end - 1; |
660 | let feature = ffi::gst_caps_features_get_nth( |
661 | self.caps_features.as_ptr(), |
662 | self.n_features as u32, |
663 | ); |
664 | debug_assert!(!feature.is_null()); |
665 | |
666 | // Safety: we can return a GStr based on the feature here because the lifetime |
667 | // of the returned Item is constrained by the underlying CapsFeatureRef. |
668 | Some(glib::GStr::from_ptr(feature)) |
669 | } |
670 | } |
671 | } |
672 | } |
673 | |
674 | impl ExactSizeIterator for Iter<'_> {} |
675 | |
676 | impl std::iter::FusedIterator for Iter<'_> {} |
677 | |
678 | impl<'a> IntoIterator for &'a CapsFeaturesRef { |
679 | type IntoIter = Iter<'a>; |
680 | type Item = &'a glib::GStr; |
681 | |
682 | fn into_iter(self) -> Self::IntoIter { |
683 | self.iter() |
684 | } |
685 | } |
686 | |
687 | impl<'a> From<&'a str> for CapsFeatures { |
688 | fn from(value: &'a str) -> Self { |
689 | skip_assert_initialized!(); |
690 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
691 | |
692 | features.add(feature:value); |
693 | |
694 | features |
695 | } |
696 | } |
697 | |
698 | impl<'a> From<&'a glib::GStr> for CapsFeatures { |
699 | fn from(value: &'a glib::GStr) -> Self { |
700 | skip_assert_initialized!(); |
701 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
702 | |
703 | features.add(feature:value); |
704 | |
705 | features |
706 | } |
707 | } |
708 | |
709 | impl From<glib::Quark> for CapsFeatures { |
710 | fn from(value: glib::Quark) -> Self { |
711 | skip_assert_initialized!(); |
712 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
713 | |
714 | features.add_from_quark(feature:value); |
715 | |
716 | features |
717 | } |
718 | } |
719 | |
720 | impl<'a, const N: usize> From<[&'a str; N]> for CapsFeatures { |
721 | fn from(value: [&'a str; N]) -> Self { |
722 | skip_assert_initialized!(); |
723 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
724 | |
725 | value.into_iter().for_each(|f: &'a str| features.add(feature:f)); |
726 | |
727 | features |
728 | } |
729 | } |
730 | |
731 | impl<'a, const N: usize> From<[&'a glib::GStr; N]> for CapsFeatures { |
732 | fn from(value: [&'a glib::GStr; N]) -> Self { |
733 | skip_assert_initialized!(); |
734 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
735 | |
736 | value.into_iter().for_each(|f: &'a GStr| features.add(feature:f)); |
737 | |
738 | features |
739 | } |
740 | } |
741 | |
742 | impl<const N: usize> From<[String; N]> for CapsFeatures { |
743 | fn from(value: [String; N]) -> Self { |
744 | skip_assert_initialized!(); |
745 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
746 | |
747 | value.into_iter().for_each(|f: String| features.add(&f)); |
748 | |
749 | features |
750 | } |
751 | } |
752 | |
753 | impl<const N: usize> From<[glib::GString; N]> for CapsFeatures { |
754 | fn from(value: [glib::GString; N]) -> Self { |
755 | skip_assert_initialized!(); |
756 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
757 | |
758 | value.into_iter().for_each(|f: GString| features.add(&f)); |
759 | |
760 | features |
761 | } |
762 | } |
763 | |
764 | impl<const N: usize> From<[glib::Quark; N]> for CapsFeatures { |
765 | fn from(value: [glib::Quark; N]) -> Self { |
766 | skip_assert_initialized!(); |
767 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
768 | |
769 | value.into_iter().for_each(|f: Quark| features.add_from_quark(feature:f)); |
770 | |
771 | features |
772 | } |
773 | } |
774 | |
775 | impl<'a> std::iter::FromIterator<&'a str> for CapsFeatures { |
776 | fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self { |
777 | skip_assert_initialized!(); |
778 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
779 | |
780 | iter.into_iter().for_each(|f: &'a str| features.add(feature:f)); |
781 | |
782 | features |
783 | } |
784 | } |
785 | |
786 | impl<'a> std::iter::FromIterator<&'a glib::GStr> for CapsFeatures { |
787 | fn from_iter<T: IntoIterator<Item = &'a glib::GStr>>(iter: T) -> Self { |
788 | assert_initialized_main_thread!(); |
789 | |
790 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
791 | |
792 | iter.into_iter().for_each(|f: &'a GStr| features.add(feature:f)); |
793 | |
794 | features |
795 | } |
796 | } |
797 | |
798 | impl std::iter::FromIterator<String> for CapsFeatures { |
799 | fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self { |
800 | skip_assert_initialized!(); |
801 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
802 | |
803 | iter.into_iter().for_each(|f: String| features.add(&f)); |
804 | |
805 | features |
806 | } |
807 | } |
808 | |
809 | impl std::iter::FromIterator<glib::GString> for CapsFeatures { |
810 | fn from_iter<T: IntoIterator<Item = glib::GString>>(iter: T) -> Self { |
811 | assert_initialized_main_thread!(); |
812 | |
813 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
814 | |
815 | iter.into_iter().for_each(|f: GString| features.add(&f)); |
816 | |
817 | features |
818 | } |
819 | } |
820 | |
821 | impl std::iter::FromIterator<glib::Quark> for CapsFeatures { |
822 | fn from_iter<T: IntoIterator<Item = glib::Quark>>(iter: T) -> Self { |
823 | skip_assert_initialized!(); |
824 | let mut features: CapsFeatures = CapsFeatures::new_empty(); |
825 | |
826 | iter.into_iter().for_each(|f: Quark| features.add_from_quark(feature:f)); |
827 | |
828 | features |
829 | } |
830 | } |
831 | |
832 | impl fmt::Debug for CapsFeaturesRef { |
833 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
834 | f&mut DebugTuple<'_, '_>.debug_tuple(name:"CapsFeatures" ) |
835 | .field(&self.to_string()) |
836 | .finish() |
837 | } |
838 | } |
839 | |
840 | impl fmt::Display for CapsFeaturesRef { |
841 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
842 | let s: GString = unsafe { |
843 | glib::GString::from_glib_full(ptr:ffi::gst_caps_features_to_string(self.as_ptr())) |
844 | }; |
845 | f.write_str(&s) |
846 | } |
847 | } |
848 | |
849 | impl ToOwned for CapsFeaturesRef { |
850 | type Owned = CapsFeatures; |
851 | |
852 | #[inline ] |
853 | fn to_owned(&self) -> CapsFeatures { |
854 | unsafe { from_glib_full(ptr:ffi::gst_caps_features_copy(self.as_ptr() as *const _) as *mut _) } |
855 | } |
856 | } |
857 | |
858 | unsafe impl Sync for CapsFeaturesRef {} |
859 | unsafe impl Send for CapsFeaturesRef {} |
860 | |
861 | pub static CAPS_FEATURE_MEMORY_SYSTEM_MEMORY: &glib::GStr = |
862 | unsafe { glib::GStr::from_utf8_with_nul_unchecked(bytes:ffi::GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY) }; |
863 | pub static CAPS_FEATURES_MEMORY_SYSTEM_MEMORY: Lazy<CapsFeatures> = |
864 | Lazy::new(|| CapsFeatures::new([CAPS_FEATURE_MEMORY_SYSTEM_MEMORY])); |
865 | |
866 | #[cfg (test)] |
867 | mod tests { |
868 | use super::*; |
869 | |
870 | #[test ] |
871 | fn test_from_value_optional() { |
872 | use glib::value::ToValue; |
873 | |
874 | crate::init().unwrap(); |
875 | |
876 | let a = None::<CapsFeatures>.to_value(); |
877 | assert!(a.get::<Option<CapsFeatures>>().unwrap().is_none()); |
878 | let b = glib::value::Value::from(&CapsFeatures::new_empty()); |
879 | assert!(b.get::<Option<CapsFeatures>>().unwrap().is_some()); |
880 | } |
881 | } |
882 | |