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