1use std::{
4 borrow::{Borrow, BorrowMut, ToOwned},
5 fmt,
6 marker::PhantomData,
7 mem,
8 ops::{Deref, DerefMut},
9 ptr, str,
10};
11
12use crate::{IdStr, ffi};
13use cfg_if::cfg_if;
14use glib::{prelude::*, translate::*};
15use std::sync::LazyLock;
16
17#[doc(alias = "GstCapsFeatures")]
36#[repr(transparent)]
37pub struct CapsFeatures(ptr::NonNull<ffi::GstCapsFeatures>);
38unsafe impl Send for CapsFeatures {}
39unsafe impl Sync for CapsFeatures {}
40
41impl CapsFeatures {
42 #[doc(alias = "gst_caps_features_new")]
51 pub fn new<S: IntoGStr>(features: impl IntoIterator<Item = S>) -> Self {
52 skip_assert_initialized!();
53 let mut f = Self::new_empty();
54
55 for feature in features {
56 f.add(feature);
57 }
58
59 f
60 }
61
62 #[doc(alias = "gst_caps_features_new_static_str")]
63 pub fn new_from_static<S: AsRef<glib::GStr> + 'static>(
64 features: impl IntoIterator<Item = S>,
65 ) -> Self {
66 skip_assert_initialized!();
67 let mut f = Self::new_empty();
68
69 for feature in features {
70 f.add_from_static(feature);
71 }
72
73 f
74 }
75
76 #[doc(alias = "gst_caps_features_new_id_str")]
77 pub fn new_from_id<S: AsRef<IdStr>>(features: impl IntoIterator<Item = S>) -> Self {
78 skip_assert_initialized!();
79 let mut f = Self::new_empty();
80
81 for feature in features {
82 f.add_from_id(feature);
83 }
84
85 f
86 }
87
88 #[deprecated = "use `new_by_id()` instead"]
89 #[allow(deprecated)]
90 #[doc(alias = "gst_caps_features_new_id")]
91 pub fn from_quarks(features: impl IntoIterator<Item = glib::Quark>) -> Self {
92 skip_assert_initialized!();
93 let mut f = Self::new_empty();
94
95 for feature in features.into_iter() {
96 f.add_from_quark(feature);
97 }
98
99 f
100 }
101
102 #[doc(alias = "gst_caps_features_new_empty")]
108 pub fn new_empty() -> Self {
109 assert_initialized_main_thread!();
110 unsafe {
111 CapsFeatures(ptr::NonNull::new_unchecked(
112 ffi::gst_caps_features_new_empty(),
113 ))
114 }
115 }
116
117 #[doc(alias = "gst_caps_features_new_any")]
125 pub fn new_any() -> Self {
126 assert_initialized_main_thread!();
127 unsafe { CapsFeatures(ptr::NonNull::new_unchecked(ffi::gst_caps_features_new_any())) }
128 }
129}
130
131impl IntoGlibPtr<*mut ffi::GstCapsFeatures> for CapsFeatures {
132 #[inline]
133 fn into_glib_ptr(self) -> *mut ffi::GstCapsFeatures {
134 let s = mem::ManuallyDrop::new(self);
135 s.0.as_ptr()
136 }
137}
138
139impl Deref for CapsFeatures {
140 type Target = CapsFeaturesRef;
141
142 #[inline]
143 fn deref(&self) -> &CapsFeaturesRef {
144 unsafe { &*(self.0.as_ref() as *const ffi::GstCapsFeatures as *const CapsFeaturesRef) }
145 }
146}
147
148impl DerefMut for CapsFeatures {
149 #[inline]
150 fn deref_mut(&mut self) -> &mut CapsFeaturesRef {
151 unsafe { &mut *(self.0.as_mut() as *mut ffi::GstCapsFeatures as *mut CapsFeaturesRef) }
152 }
153}
154
155impl AsRef<CapsFeaturesRef> for CapsFeatures {
156 #[inline]
157 fn as_ref(&self) -> &CapsFeaturesRef {
158 self.deref()
159 }
160}
161
162impl AsMut<CapsFeaturesRef> for CapsFeatures {
163 #[inline]
164 fn as_mut(&mut self) -> &mut CapsFeaturesRef {
165 self.deref_mut()
166 }
167}
168
169impl Clone for CapsFeatures {
170 #[inline]
171 fn clone(&self) -> Self {
172 unsafe {
173 let ptr = ffi::gst_caps_features_copy(self.0.as_ref());
174 debug_assert!(!ptr.is_null());
175 CapsFeatures(ptr::NonNull::new_unchecked(ptr))
176 }
177 }
178}
179
180impl Drop for CapsFeatures {
181 #[inline]
182 fn drop(&mut self) {
183 unsafe { ffi::gst_caps_features_free(self.0.as_mut()) }
184 }
185}
186
187impl fmt::Debug for CapsFeatures {
188 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
189 f.debug_tuple("CapsFeatures")
190 .field(&self.to_string())
191 .finish()
192 }
193}
194
195impl fmt::Display for CapsFeatures {
196 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 f.write_str(&CapsFeaturesRef::to_string(self.as_ref()))
200 }
201}
202
203impl str::FromStr for CapsFeatures {
204 type Err = glib::BoolError;
205
206 #[doc(alias = "gst_caps_features_from_string")]
207 fn from_str(s: &str) -> Result<Self, Self::Err> {
208 assert_initialized_main_thread!();
209 unsafe {
210 let ptr = s.run_with_gstr(|s| ffi::gst_caps_features_from_string(s.as_ptr()));
211 if ptr.is_null() {
212 return Err(glib::bool_error!(
213 "Failed to parse caps features from string"
214 ));
215 }
216
217 Ok(Self(ptr::NonNull::new_unchecked(ptr)))
218 }
219 }
220}
221
222impl Borrow<CapsFeaturesRef> for CapsFeatures {
223 #[inline]
224 fn borrow(&self) -> &CapsFeaturesRef {
225 self.as_ref()
226 }
227}
228
229impl BorrowMut<CapsFeaturesRef> for CapsFeatures {
230 #[inline]
231 fn borrow_mut(&mut self) -> &mut CapsFeaturesRef {
232 self.as_mut()
233 }
234}
235
236impl glib::types::StaticType for CapsFeatures {
237 #[inline]
238 fn static_type() -> glib::types::Type {
239 unsafe { from_glib(ffi::gst_caps_features_get_type()) }
240 }
241}
242
243impl<'a> ToGlibPtr<'a, *const ffi::GstCapsFeatures> for CapsFeatures {
244 type Storage = PhantomData<&'a Self>;
245
246 #[inline]
247 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstCapsFeatures, Self> {
248 unsafe { Stash(self.0.as_ref(), PhantomData) }
249 }
250
251 #[inline]
252 fn to_glib_full(&self) -> *const ffi::GstCapsFeatures {
253 unsafe { ffi::gst_caps_features_copy(self.0.as_ref()) }
254 }
255}
256
257impl<'a> ToGlibPtr<'a, *mut ffi::GstCapsFeatures> for CapsFeatures {
258 type Storage = PhantomData<&'a Self>;
259
260 #[inline]
261 fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GstCapsFeatures, Self> {
262 unsafe {
263 Stash(
264 self.0.as_ref() as *const ffi::GstCapsFeatures as *mut ffi::GstCapsFeatures,
265 PhantomData,
266 )
267 }
268 }
269
270 #[inline]
271 fn to_glib_full(&self) -> *mut ffi::GstCapsFeatures {
272 unsafe { ffi::gst_caps_features_copy(self.0.as_ref()) }
273 }
274}
275
276impl<'a> ToGlibPtrMut<'a, *mut ffi::GstCapsFeatures> for CapsFeatures {
277 type Storage = PhantomData<&'a mut Self>;
278
279 #[inline]
280 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GstCapsFeatures, Self> {
281 unsafe { StashMut(self.0.as_mut(), PhantomData) }
282 }
283}
284
285impl FromGlibPtrNone<*const ffi::GstCapsFeatures> for CapsFeatures {
286 #[inline]
287 unsafe fn from_glib_none(ptr: *const ffi::GstCapsFeatures) -> Self {
288 unsafe {
289 debug_assert!(!ptr.is_null());
290 let ptr = ffi::gst_caps_features_copy(ptr);
291 debug_assert!(!ptr.is_null());
292 CapsFeatures(ptr::NonNull::new_unchecked(ptr))
293 }
294 }
295}
296
297impl FromGlibPtrNone<*mut ffi::GstCapsFeatures> for CapsFeatures {
298 #[inline]
299 unsafe fn from_glib_none(ptr: *mut ffi::GstCapsFeatures) -> Self {
300 unsafe {
301 debug_assert!(!ptr.is_null());
302 let ptr = ffi::gst_caps_features_copy(ptr);
303 debug_assert!(!ptr.is_null());
304 CapsFeatures(ptr::NonNull::new_unchecked(ptr))
305 }
306 }
307}
308
309impl FromGlibPtrFull<*const ffi::GstCapsFeatures> for CapsFeatures {
310 #[inline]
311 unsafe fn from_glib_full(ptr: *const ffi::GstCapsFeatures) -> Self {
312 unsafe {
313 debug_assert!(!ptr.is_null());
314 CapsFeatures(ptr::NonNull::new_unchecked(
315 ptr as *mut ffi::GstCapsFeatures,
316 ))
317 }
318 }
319}
320
321impl FromGlibPtrFull<*mut ffi::GstCapsFeatures> for CapsFeatures {
322 #[inline]
323 unsafe fn from_glib_full(ptr: *mut ffi::GstCapsFeatures) -> Self {
324 unsafe {
325 debug_assert!(!ptr.is_null());
326 CapsFeatures(ptr::NonNull::new_unchecked(ptr))
327 }
328 }
329}
330
331impl glib::value::ValueType for CapsFeatures {
332 type Type = Self;
333}
334
335impl glib::value::ValueTypeOptional for CapsFeatures {}
336
337unsafe impl<'a> glib::value::FromValue<'a> for CapsFeatures {
338 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
339
340 unsafe fn from_value(value: &'a glib::Value) -> Self {
341 unsafe {
342 skip_assert_initialized!();
343 from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
344 as *mut ffi::GstCapsFeatures)
345 }
346 }
347}
348
349impl glib::value::ToValue for CapsFeatures {
350 fn to_value(&self) -> glib::Value {
351 let mut value = glib::Value::for_value_type::<Self>();
352 unsafe {
353 glib::gobject_ffi::g_value_set_boxed(
354 value.to_glib_none_mut().0,
355 ToGlibPtr::<*mut ffi::GstCapsFeatures>::to_glib_none(self).0 as *mut _,
356 )
357 }
358 value
359 }
360
361 fn value_type(&self) -> glib::Type {
362 Self::static_type()
363 }
364}
365
366impl glib::value::ToValueOptional for CapsFeatures {
367 fn to_value_optional(s: Option<&Self>) -> glib::Value {
368 skip_assert_initialized!();
369 let mut value = glib::Value::for_value_type::<Self>();
370 unsafe {
371 glib::gobject_ffi::g_value_set_boxed(
372 value.to_glib_none_mut().0,
373 ToGlibPtr::<*mut ffi::GstCapsFeatures>::to_glib_none(&s).0 as *mut _,
374 )
375 }
376 value
377 }
378}
379
380impl From<CapsFeatures> for glib::Value {
381 fn from(v: CapsFeatures) -> glib::Value {
382 skip_assert_initialized!();
383 let mut value = glib::Value::for_value_type::<CapsFeatures>();
384 unsafe {
385 glib::gobject_ffi::g_value_take_boxed(
386 value.to_glib_none_mut().0,
387 IntoGlibPtr::<*mut ffi::GstCapsFeatures>::into_glib_ptr(v) as *mut _,
388 )
389 }
390 value
391 }
392}
393
394impl GlibPtrDefault for CapsFeatures {
395 type GlibType = *mut ffi::GstCapsFeatures;
396}
397
398unsafe impl TransparentPtrType for CapsFeatures {}
399
400#[repr(transparent)]
401#[doc(alias = "GstCapsFeatures")]
402pub struct CapsFeaturesRef(ffi::GstCapsFeatures);
403
404impl CapsFeaturesRef {
405 #[inline]
406 pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstCapsFeatures) -> &'a CapsFeaturesRef {
407 unsafe {
408 debug_assert!(!ptr.is_null());
409
410 &*(ptr as *mut CapsFeaturesRef)
411 }
412 }
413
414 #[inline]
415 pub unsafe fn from_glib_borrow_mut<'a>(
416 ptr: *mut ffi::GstCapsFeatures,
417 ) -> &'a mut CapsFeaturesRef {
418 unsafe {
419 debug_assert!(!ptr.is_null());
420
421 &mut *(ptr as *mut CapsFeaturesRef)
422 }
423 }
424
425 #[inline]
426 pub fn as_ptr(&self) -> *const ffi::GstCapsFeatures {
427 self as *const Self as *const ffi::GstCapsFeatures
428 }
429
430 #[inline]
431 pub fn as_mut_ptr(&self) -> *mut ffi::GstCapsFeatures {
432 self as *const Self as *mut ffi::GstCapsFeatures
433 }
434
435 pub fn is_empty(&self) -> bool {
436 self.size() == 0 && !self.is_any()
437 }
438
439 #[doc(alias = "gst_caps_features_is_any")]
440 pub fn is_any(&self) -> bool {
441 unsafe { from_glib(ffi::gst_caps_features_is_any(self.as_ptr())) }
442 }
443
444 #[doc(alias = "gst_caps_features_contains")]
445 pub fn contains(&self, feature: impl IntoGStr) -> bool {
446 unsafe {
447 feature.run_with_gstr(|feature| {
448 from_glib(ffi::gst_caps_features_contains(
449 self.as_ptr(),
450 feature.as_ptr(),
451 ))
452 })
453 }
454 }
455
456 #[doc(alias = "gst_caps_features_contains_id_str")]
457 pub fn contains_by_id(&self, feature: impl AsRef<IdStr>) -> bool {
458 unsafe {
459 cfg_if! {
460 if #[cfg(feature = "v1_26")] {
461 from_glib(ffi::gst_caps_features_contains_id_str(
462 self.as_ptr(),
463 feature.as_ref().as_ptr(),
464 ))
465 } else {
466 from_glib(ffi::gst_caps_features_contains(
467 self.as_ptr(),
468 feature.as_ref().as_gstr().as_ptr(),
469 ))
470 }
471 }
472 }
473 }
474
475 #[deprecated = "use `contains_by_id()` instead"]
476 #[doc(alias = "gst_caps_features_contains_id")]
477 pub fn contains_quark(&self, feature: glib::Quark) -> bool {
478 unsafe {
479 from_glib(ffi::gst_caps_features_contains_id(
480 self.as_ptr(),
481 feature.into_glib(),
482 ))
483 }
484 }
485
486 #[doc(alias = "get_size")]
487 #[doc(alias = "gst_caps_features_get_size")]
488 pub fn size(&self) -> usize {
489 unsafe { ffi::gst_caps_features_get_size(self.as_ptr()) as usize }
490 }
491
492 #[doc(alias = "get_nth")]
493 #[doc(alias = "gst_caps_features_get_nth")]
494 pub fn nth(&self, idx: usize) -> Option<&glib::GStr> {
495 if idx >= self.size() {
496 return None;
497 }
498
499 unsafe {
500 let feature = ffi::gst_caps_features_get_nth(self.as_ptr(), idx as u32);
501 if feature.is_null() {
502 return None;
503 }
504
505 Some(glib::GStr::from_ptr(feature))
506 }
507 }
508
509 #[cfg(feature = "v1_26")]
510 #[doc(alias = "get_nth_by_id")]
511 #[doc(alias = "gst_caps_features_get_nth_id_str")]
512 pub fn nth_id(&self, idx: usize) -> Option<&IdStr> {
513 if idx >= self.size() {
514 return None;
515 }
516
517 unsafe {
518 let feature = ffi::gst_caps_features_get_nth_id_str(self.as_ptr(), idx as u32);
519 if feature.is_null() {
520 return None;
521 }
522
523 Some(&*(feature as *const IdStr))
524 }
525 }
526
527 #[deprecated = "use `nth_by_id()` instead"]
528 #[doc(alias = "gst_caps_features_get_nth_id")]
529 pub fn nth_quark(&self, idx: usize) -> Option<glib::Quark> {
530 if idx >= self.size() {
531 return None;
532 }
533
534 unsafe {
535 let feature = ffi::gst_caps_features_get_nth_id(self.as_ptr(), idx as u32);
536 Some(from_glib(feature))
537 }
538 }
539
540 #[doc(alias = "gst_caps_features_add")]
541 pub fn add(&mut self, feature: impl IntoGStr) {
542 unsafe {
543 feature.run_with_gstr(|feature| {
544 ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ptr())
545 })
546 }
547 }
548
549 #[doc(alias = "gst_caps_features_add_static_str")]
550 pub fn add_from_static(&mut self, feature: impl AsRef<glib::GStr> + 'static) {
551 unsafe {
552 cfg_if! {
553 if #[cfg(feature = "v1_26")] {
554 ffi::gst_caps_features_add_static_str(self.as_mut_ptr(), feature.as_ref().as_ptr())
555 } else {
556 ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ref().as_ptr())
557 }
558 }
559 }
560 }
561
562 #[doc(alias = "gst_caps_features_add_id_str")]
563 pub fn add_from_id(&mut self, feature: impl AsRef<IdStr>) {
564 unsafe {
565 cfg_if! {
566 if #[cfg(feature = "v1_26")] {
567 ffi::gst_caps_features_add_id_str(self.as_mut_ptr(), feature.as_ref().as_ptr())
568 } else {
569 ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ref().as_gstr().as_ptr())
570 }
571 }
572 }
573 }
574
575 #[doc(alias = "gst_caps_features_remove")]
576 pub fn remove(&mut self, feature: impl IntoGStr) {
577 unsafe {
578 feature.run_with_gstr(|feature| {
579 ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.as_ptr())
580 })
581 }
582 }
583
584 #[doc(alias = "gst_caps_features_remove_id_str")]
585 pub fn remove_by_id(&mut self, feature: impl AsRef<IdStr>) {
586 unsafe {
587 cfg_if! {
588 if #[cfg(feature = "v1_26")] {
589 ffi::gst_caps_features_remove_id_str(self.as_mut_ptr(), feature.as_ref().as_ptr())
590 } else {
591 ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.as_ref().as_gstr().as_ptr())
592 }
593 }
594 }
595 }
596
597 #[deprecated = "use `add_by_id()` instead"]
598 #[doc(alias = "gst_caps_features_add_id")]
599 pub fn add_from_quark(&mut self, feature: glib::Quark) {
600 unsafe { ffi::gst_caps_features_add_id(self.as_mut_ptr(), feature.into_glib()) }
601 }
602
603 #[deprecated = "use `remove_by_id()` instead"]
604 #[doc(alias = "gst_caps_features_remove_id")]
605 pub fn remove_by_quark(&mut self, feature: glib::Quark) {
606 unsafe { ffi::gst_caps_features_remove_id(self.as_mut_ptr(), feature.into_glib()) }
607 }
608
609 pub fn iter(&self) -> Iter<'_> {
610 Iter::new(self)
611 }
612
613 #[doc(alias = "gst_caps_features_is_equal")]
615 pub fn is_equal(&self, other: &CapsFeaturesRef) -> bool {
616 unsafe {
617 from_glib(ffi::gst_caps_features_is_equal(
618 self.as_ptr(),
619 other.as_ptr(),
620 ))
621 }
622 }
623}
624
625impl glib::types::StaticType for CapsFeaturesRef {
626 #[inline]
627 fn static_type() -> glib::types::Type {
628 unsafe { from_glib(ffi::gst_structure_get_type()) }
629 }
630}
631
632impl<'a> std::iter::Extend<&'a str> for CapsFeaturesRef {
633 fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) {
634 iter.into_iter().for_each(|f| self.add(f));
635 }
636}
637
638impl<'a> std::iter::Extend<&'a glib::GStr> for CapsFeaturesRef {
639 fn extend<T: IntoIterator<Item = &'a glib::GStr>>(&mut self, iter: T) {
640 iter.into_iter().for_each(|f| self.add(f));
641 }
642}
643
644impl std::iter::Extend<String> for CapsFeaturesRef {
645 fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
646 iter.into_iter().for_each(|f| self.add(&f));
647 }
648}
649
650impl std::iter::Extend<glib::GString> for CapsFeaturesRef {
651 fn extend<T: IntoIterator<Item = glib::GString>>(&mut self, iter: T) {
652 iter.into_iter().for_each(|f| self.add(&f));
653 }
654}
655
656impl<Id: AsRef<IdStr>> std::iter::Extend<Id> for CapsFeaturesRef {
657 fn extend<T: IntoIterator<Item = Id>>(&mut self, iter: T) {
658 iter.into_iter().for_each(|f| self.add_from_id(f));
659 }
660}
661
662impl std::iter::Extend<glib::Quark> for CapsFeaturesRef {
663 #[allow(deprecated)]
664 fn extend<T: IntoIterator<Item = glib::Quark>>(&mut self, iter: T) {
665 iter.into_iter().for_each(|f| self.add_from_quark(f));
666 }
667}
668
669unsafe impl<'a> glib::value::FromValue<'a> for &'a CapsFeaturesRef {
670 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
671
672 unsafe fn from_value(value: &'a glib::Value) -> Self {
673 unsafe {
674 skip_assert_initialized!();
675 &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
676 as *const CapsFeaturesRef)
677 }
678 }
679}
680
681impl glib::value::ToValue for CapsFeaturesRef {
682 fn to_value(&self) -> glib::Value {
683 let mut value = glib::Value::for_value_type::<CapsFeatures>();
684 unsafe {
685 glib::gobject_ffi::g_value_set_boxed(
686 value.to_glib_none_mut().0,
687 self.as_mut_ptr() as *mut _,
688 )
689 }
690 value
691 }
692
693 fn value_type(&self) -> glib::Type {
694 Self::static_type()
695 }
696}
697
698impl glib::value::ToValueOptional for CapsFeaturesRef {
699 fn to_value_optional(s: Option<&Self>) -> glib::Value {
700 skip_assert_initialized!();
701 let mut value = glib::Value::for_value_type::<CapsFeatures>();
702 unsafe {
703 glib::gobject_ffi::g_value_set_boxed(
704 value.to_glib_none_mut().0,
705 s.map(|s| s.as_mut_ptr()).unwrap_or(ptr::null_mut()) as *mut _,
706 )
707 }
708 value
709 }
710}
711
712crate::utils::define_fixed_size_iter!(
713 Iter,
714 &'a CapsFeaturesRef,
715 &'a glib::GStr,
716 |collection: &CapsFeaturesRef| collection.size(),
717 |collection: &CapsFeaturesRef, idx: usize| unsafe {
718 let feature = ffi::gst_caps_features_get_nth(collection.as_ptr(), idx as u32);
719 glib::GStr::from_ptr(feature)
720 }
721);
722
723impl<'a> IntoIterator for &'a CapsFeaturesRef {
724 type IntoIter = Iter<'a>;
725 type Item = &'a glib::GStr;
726
727 fn into_iter(self) -> Self::IntoIter {
728 self.iter()
729 }
730}
731
732impl<'a> From<&'a str> for CapsFeatures {
733 fn from(value: &'a str) -> Self {
734 skip_assert_initialized!();
735 let mut features = CapsFeatures::new_empty();
736
737 features.add(value);
738
739 features
740 }
741}
742
743impl<'a> From<&'a glib::GStr> for CapsFeatures {
744 fn from(value: &'a glib::GStr) -> Self {
745 skip_assert_initialized!();
746 let mut features = CapsFeatures::new_empty();
747
748 features.add(value);
749
750 features
751 }
752}
753
754impl<Id: AsRef<IdStr>> From<Id> for CapsFeatures {
755 fn from(value: Id) -> Self {
756 skip_assert_initialized!();
757 let mut features = CapsFeatures::new_empty();
758
759 features.add_from_id(value);
760
761 features
762 }
763}
764
765impl From<glib::Quark> for CapsFeatures {
766 #[allow(deprecated)]
767 fn from(value: glib::Quark) -> Self {
768 skip_assert_initialized!();
769 let mut features = CapsFeatures::new_empty();
770
771 features.add_from_quark(value);
772
773 features
774 }
775}
776
777impl<'a, const N: usize> From<[&'a str; N]> for CapsFeatures {
778 fn from(value: [&'a str; N]) -> Self {
779 skip_assert_initialized!();
780 let mut features = CapsFeatures::new_empty();
781
782 value.into_iter().for_each(|f| features.add(f));
783
784 features
785 }
786}
787
788impl<'a, const N: usize> From<[&'a glib::GStr; N]> for CapsFeatures {
789 fn from(value: [&'a glib::GStr; N]) -> Self {
790 skip_assert_initialized!();
791 let mut features = CapsFeatures::new_empty();
792
793 value.into_iter().for_each(|f| features.add(f));
794
795 features
796 }
797}
798
799impl<const N: usize> From<[String; N]> for CapsFeatures {
800 fn from(value: [String; N]) -> Self {
801 skip_assert_initialized!();
802 let mut features = CapsFeatures::new_empty();
803
804 value.into_iter().for_each(|f| features.add(&f));
805
806 features
807 }
808}
809
810impl<const N: usize> From<[glib::GString; N]> for CapsFeatures {
811 fn from(value: [glib::GString; N]) -> Self {
812 skip_assert_initialized!();
813 let mut features = CapsFeatures::new_empty();
814
815 value.into_iter().for_each(|f| features.add(&f));
816
817 features
818 }
819}
820
821impl<const N: usize, Id: AsRef<IdStr>> From<[Id; N]> for CapsFeatures {
822 fn from(value: [Id; N]) -> Self {
823 skip_assert_initialized!();
824 let mut features = CapsFeatures::new_empty();
825
826 value.into_iter().for_each(|f| features.add_from_id(f));
827
828 features
829 }
830}
831
832impl<const N: usize> From<[glib::Quark; N]> for CapsFeatures {
833 #[allow(deprecated)]
834 fn from(value: [glib::Quark; N]) -> Self {
835 skip_assert_initialized!();
836 let mut features = CapsFeatures::new_empty();
837
838 value.into_iter().for_each(|f| features.add_from_quark(f));
839
840 features
841 }
842}
843
844impl<'a> std::iter::FromIterator<&'a str> for CapsFeatures {
845 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
846 skip_assert_initialized!();
847 let mut features = CapsFeatures::new_empty();
848
849 iter.into_iter().for_each(|f| features.add(f));
850
851 features
852 }
853}
854
855impl<'a> std::iter::FromIterator<&'a glib::GStr> for CapsFeatures {
856 fn from_iter<T: IntoIterator<Item = &'a glib::GStr>>(iter: T) -> Self {
857 assert_initialized_main_thread!();
858
859 let mut features = CapsFeatures::new_empty();
860
861 iter.into_iter().for_each(|f| features.add(f));
862
863 features
864 }
865}
866
867impl std::iter::FromIterator<String> for CapsFeatures {
868 fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
869 skip_assert_initialized!();
870 let mut features = CapsFeatures::new_empty();
871
872 iter.into_iter().for_each(|f| features.add(&f));
873
874 features
875 }
876}
877
878impl std::iter::FromIterator<glib::GString> for CapsFeatures {
879 fn from_iter<T: IntoIterator<Item = glib::GString>>(iter: T) -> Self {
880 assert_initialized_main_thread!();
881
882 let mut features = CapsFeatures::new_empty();
883
884 iter.into_iter().for_each(|f| features.add(&f));
885
886 features
887 }
888}
889
890impl<Id: AsRef<IdStr>> std::iter::FromIterator<Id> for CapsFeatures {
891 #[allow(deprecated)]
892 fn from_iter<T: IntoIterator<Item = Id>>(iter: T) -> Self {
893 skip_assert_initialized!();
894 let mut features = CapsFeatures::new_empty();
895
896 iter.into_iter().for_each(|f| features.add_from_id(f));
897
898 features
899 }
900}
901
902impl std::iter::FromIterator<glib::Quark> for CapsFeatures {
903 #[allow(deprecated)]
904 fn from_iter<T: IntoIterator<Item = glib::Quark>>(iter: T) -> Self {
905 skip_assert_initialized!();
906 let mut features = CapsFeatures::new_empty();
907
908 iter.into_iter().for_each(|f| features.add_from_quark(f));
909
910 features
911 }
912}
913
914impl fmt::Debug for CapsFeaturesRef {
915 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
916 f.debug_tuple("CapsFeatures")
917 .field(&self.to_string())
918 .finish()
919 }
920}
921
922impl fmt::Display for CapsFeaturesRef {
923 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
924 let s = unsafe {
925 glib::GString::from_glib_full(ffi::gst_caps_features_to_string(self.as_ptr()))
926 };
927 f.write_str(&s)
928 }
929}
930
931impl ToOwned for CapsFeaturesRef {
932 type Owned = CapsFeatures;
933
934 #[inline]
935 fn to_owned(&self) -> CapsFeatures {
936 unsafe { from_glib_full(ffi::gst_caps_features_copy(self.as_ptr() as *const _) as *mut _) }
937 }
938}
939
940impl std::hash::Hash for CapsFeaturesRef {
941 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
942 use std::hash::{DefaultHasher, Hasher};
943
944 if self.is_any() {
946 "ANY".hash(state);
947 } else if self.is_empty() {
948 "EMPTY".hash(state);
949 } else {
950 let mut features_hash = 0;
951 for f in self.iter() {
952 let mut field_hasher = DefaultHasher::new();
953 f.hash(&mut field_hasher);
954
955 features_hash ^= field_hasher.finish();
956 }
957 features_hash.hash(state);
958 }
959 }
960}
961
962impl std::hash::Hash for CapsFeatures {
963 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
964 self.as_ref().hash(state);
965 }
966}
967
968unsafe impl Sync for CapsFeaturesRef {}
969unsafe impl Send for CapsFeaturesRef {}
970
971pub static CAPS_FEATURE_MEMORY_SYSTEM_MEMORY: &glib::GStr =
972 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY) };
973pub static CAPS_FEATURES_MEMORY_SYSTEM_MEMORY: LazyLock<CapsFeatures> =
974 LazyLock::new(|| CapsFeatures::new([CAPS_FEATURE_MEMORY_SYSTEM_MEMORY]));
975
976#[cfg(test)]
977mod tests {
978 use super::*;
979 use glib::gstr;
980
981 #[test]
982 fn test_from_value_optional() {
983 use glib::value::ToValue;
984
985 crate::init().unwrap();
986
987 let a = None::<CapsFeatures>.to_value();
988 assert!(a.get::<Option<CapsFeatures>>().unwrap().is_none());
989 let b = glib::value::Value::from(&CapsFeatures::new_empty());
990 assert!(b.get::<Option<CapsFeatures>>().unwrap().is_some());
991 }
992
993 #[test]
994 fn trait_impls() {
995 crate::init().unwrap();
996
997 let cf = CapsFeatures::from(gstr!("memory:DMABuf"));
998 assert!(cf.contains(gstr!("memory:DMABuf")));
999
1000 let cf = CapsFeatures::from([
1001 gstr!("memory:DMABuf"),
1002 gstr!("meta:GstVideoOverlayComposition"),
1003 ]);
1004
1005 assert!(cf.contains(gstr!("memory:DMABuf")));
1006 assert!(cf.contains("meta:GstVideoOverlayComposition"));
1007 assert!(!cf.contains("memory:GLMemory"));
1008
1009 let cf = CapsFeatures::from_iter(vec![
1010 gstr!("memory:DMABuf"),
1011 gstr!("meta:GstVideoOverlayComposition"),
1012 ]);
1013
1014 assert!(cf.contains(gstr!("memory:DMABuf")));
1015 assert!(cf.contains("meta:GstVideoOverlayComposition"));
1016 assert!(!cf.contains("memory:GLMemory"));
1017
1018 let mut cf = CapsFeatures::new_empty();
1019 cf.extend([
1020 gstr!("memory:DMABuf"),
1021 gstr!("meta:GstVideoOverlayComposition"),
1022 ]);
1023
1024 assert!(cf.contains(gstr!("memory:DMABuf")));
1025 assert!(cf.contains("meta:GstVideoOverlayComposition"));
1026 assert!(!cf.contains("memory:GLMemory"));
1027 }
1028
1029 #[test]
1030 fn trait_impls_from_id() {
1031 crate::init().unwrap();
1032
1033 let cf = CapsFeatures::from(idstr!("memory:DMABuf"));
1034 assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
1035
1036 let cf = CapsFeatures::from([
1037 idstr!("memory:DMABuf"),
1038 idstr!("meta:GstVideoOverlayComposition"),
1039 ]);
1040
1041 assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
1042 assert!(cf.contains("meta:GstVideoOverlayComposition"));
1043 assert!(!cf.contains("memory:GLMemory"));
1044
1045 let cf = CapsFeatures::from_iter(vec![
1046 idstr!("memory:DMABuf"),
1047 idstr!("meta:GstVideoOverlayComposition"),
1048 ]);
1049
1050 assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
1051 assert!(cf.contains("meta:GstVideoOverlayComposition"));
1052 assert!(!cf.contains("memory:GLMemory"));
1053
1054 let mut cf = CapsFeatures::new_empty();
1055 cf.extend([
1056 idstr!("memory:DMABuf"),
1057 idstr!("meta:GstVideoOverlayComposition"),
1058 ]);
1059
1060 assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
1061 assert!(cf.contains("meta:GstVideoOverlayComposition"));
1062 assert!(!cf.contains("memory:GLMemory"));
1063 }
1064
1065 #[test]
1066 fn trait_impls_from_ref_id() {
1067 crate::init().unwrap();
1068
1069 let dma_buf = idstr!("memory:DMABuf");
1070 let overlay_comp = idstr!("meta:GstVideoOverlayComposition");
1071
1072 let cf = CapsFeatures::from(&dma_buf);
1073 assert!(cf.contains_by_id(&dma_buf));
1074
1075 let cf = CapsFeatures::from([&dma_buf, &overlay_comp]);
1076
1077 assert!(cf.contains_by_id(&dma_buf));
1078 assert!(cf.contains_by_id(&overlay_comp));
1079 assert!(!cf.contains("memory:GLMemory"));
1080
1081 let cf = CapsFeatures::from_iter(vec![&dma_buf, &overlay_comp]);
1082
1083 assert!(cf.contains_by_id(&dma_buf));
1084 assert!(cf.contains_by_id(&overlay_comp));
1085 assert!(!cf.contains("memory:GLMemory"));
1086
1087 let mut cf = CapsFeatures::new_empty();
1088 cf.extend([&dma_buf, &overlay_comp]);
1089
1090 assert!(cf.contains_by_id(dma_buf));
1091 assert!(cf.contains_by_id(overlay_comp));
1092 assert!(!cf.contains("memory:GLMemory"));
1093 }
1094
1095 #[test]
1096 fn test_hash() {
1097 crate::init().unwrap();
1098
1099 use std::hash::BuildHasher;
1100 let bh = std::hash::RandomState::new();
1101
1102 let any = CapsFeatures::new_any();
1103 let empty = CapsFeatures::new_empty();
1104 assert_eq!(bh.hash_one(&any), bh.hash_one(&any));
1105 assert_eq!(bh.hash_one(&empty), bh.hash_one(&empty));
1106 assert_ne!(bh.hash_one(&any), bh.hash_one(&empty));
1107
1108 let cf1 = CapsFeatures::from(gstr!("memory:DMABuf"));
1110 let cf2 = CapsFeatures::from(gstr!("memory:GLMemory"));
1111 assert_eq!(bh.hash_one(&cf1), bh.hash_one(&cf1));
1112 assert_eq!(bh.hash_one(&cf2), bh.hash_one(&cf2));
1113 assert_ne!(bh.hash_one(&cf1), bh.hash_one(&cf2));
1114
1115 let cf1 = CapsFeatures::from([
1117 gstr!("memory:DMABuf"),
1118 gstr!("meta:GstVideoOverlayComposition"),
1119 ]);
1120 let cf2 = CapsFeatures::from([
1121 gstr!("meta:GstVideoOverlayComposition"),
1122 gstr!("memory:DMABuf"),
1123 ]);
1124 assert_eq!(bh.hash_one(&cf1), bh.hash_one(&cf1));
1125 assert_eq!(bh.hash_one(&cf2), bh.hash_one(&cf2));
1126 assert_eq!(bh.hash_one(&cf1), bh.hash_one(&cf2));
1127 }
1128}