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::{ffi, IdStr};
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 debug_assert!(!ptr.is_null());
251 let ptr = ffi::gst_caps_features_copy(ptr);
252 debug_assert!(!ptr.is_null());
253 CapsFeatures(ptr::NonNull::new_unchecked(ptr))
254 }
255}
256
257impl FromGlibPtrNone<*mut ffi::GstCapsFeatures> for CapsFeatures {
258 #[inline]
259 unsafe fn from_glib_none(ptr: *mut ffi::GstCapsFeatures) -> Self {
260 debug_assert!(!ptr.is_null());
261 let ptr = ffi::gst_caps_features_copy(ptr);
262 debug_assert!(!ptr.is_null());
263 CapsFeatures(ptr::NonNull::new_unchecked(ptr))
264 }
265}
266
267impl FromGlibPtrFull<*const ffi::GstCapsFeatures> for CapsFeatures {
268 #[inline]
269 unsafe fn from_glib_full(ptr: *const ffi::GstCapsFeatures) -> Self {
270 debug_assert!(!ptr.is_null());
271 CapsFeatures(ptr::NonNull::new_unchecked(
272 ptr as *mut ffi::GstCapsFeatures,
273 ))
274 }
275}
276
277impl FromGlibPtrFull<*mut ffi::GstCapsFeatures> for CapsFeatures {
278 #[inline]
279 unsafe fn from_glib_full(ptr: *mut ffi::GstCapsFeatures) -> Self {
280 debug_assert!(!ptr.is_null());
281 CapsFeatures(ptr::NonNull::new_unchecked(ptr))
282 }
283}
284
285impl glib::value::ValueType for CapsFeatures {
286 type Type = Self;
287}
288
289impl glib::value::ValueTypeOptional for CapsFeatures {}
290
291unsafe impl<'a> glib::value::FromValue<'a> for CapsFeatures {
292 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
293
294 unsafe fn from_value(value: &'a glib::Value) -> Self {
295 skip_assert_initialized!();
296 from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
297 as *mut ffi::GstCapsFeatures)
298 }
299}
300
301impl glib::value::ToValue for CapsFeatures {
302 fn to_value(&self) -> glib::Value {
303 let mut value = glib::Value::for_value_type::<Self>();
304 unsafe {
305 glib::gobject_ffi::g_value_set_boxed(
306 value.to_glib_none_mut().0,
307 ToGlibPtr::<*mut ffi::GstCapsFeatures>::to_glib_none(self).0 as *mut _,
308 )
309 }
310 value
311 }
312
313 fn value_type(&self) -> glib::Type {
314 Self::static_type()
315 }
316}
317
318impl glib::value::ToValueOptional for CapsFeatures {
319 fn to_value_optional(s: Option<&Self>) -> glib::Value {
320 skip_assert_initialized!();
321 let mut value = glib::Value::for_value_type::<Self>();
322 unsafe {
323 glib::gobject_ffi::g_value_set_boxed(
324 value.to_glib_none_mut().0,
325 ToGlibPtr::<*mut ffi::GstCapsFeatures>::to_glib_none(&s).0 as *mut _,
326 )
327 }
328 value
329 }
330}
331
332impl From<CapsFeatures> for glib::Value {
333 fn from(v: CapsFeatures) -> glib::Value {
334 skip_assert_initialized!();
335 let mut value = glib::Value::for_value_type::<CapsFeatures>();
336 unsafe {
337 glib::gobject_ffi::g_value_take_boxed(
338 value.to_glib_none_mut().0,
339 IntoGlibPtr::<*mut ffi::GstCapsFeatures>::into_glib_ptr(v) as *mut _,
340 )
341 }
342 value
343 }
344}
345
346impl GlibPtrDefault for CapsFeatures {
347 type GlibType = *mut ffi::GstCapsFeatures;
348}
349
350unsafe impl TransparentPtrType for CapsFeatures {}
351
352#[repr(transparent)]
353#[doc(alias = "GstCapsFeatures")]
354pub struct CapsFeaturesRef(ffi::GstCapsFeatures);
355
356impl CapsFeaturesRef {
357 #[inline]
358 pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstCapsFeatures) -> &'a CapsFeaturesRef {
359 debug_assert!(!ptr.is_null());
360
361 &*(ptr as *mut CapsFeaturesRef)
362 }
363
364 #[inline]
365 pub unsafe fn from_glib_borrow_mut<'a>(
366 ptr: *mut ffi::GstCapsFeatures,
367 ) -> &'a mut CapsFeaturesRef {
368 debug_assert!(!ptr.is_null());
369
370 &mut *(ptr as *mut CapsFeaturesRef)
371 }
372
373 #[inline]
374 pub fn as_ptr(&self) -> *const ffi::GstCapsFeatures {
375 self as *const Self as *const ffi::GstCapsFeatures
376 }
377
378 #[inline]
379 pub fn as_mut_ptr(&self) -> *mut ffi::GstCapsFeatures {
380 self as *const Self as *mut ffi::GstCapsFeatures
381 }
382
383 pub fn is_empty(&self) -> bool {
384 self.size() == 0 && !self.is_any()
385 }
386
387 #[doc(alias = "gst_caps_features_is_any")]
388 pub fn is_any(&self) -> bool {
389 unsafe { from_glib(ffi::gst_caps_features_is_any(self.as_ptr())) }
390 }
391
392 #[doc(alias = "gst_caps_features_contains")]
393 pub fn contains(&self, feature: impl IntoGStr) -> bool {
394 unsafe {
395 feature.run_with_gstr(|feature| {
396 from_glib(ffi::gst_caps_features_contains(
397 self.as_ptr(),
398 feature.as_ptr(),
399 ))
400 })
401 }
402 }
403
404 #[doc(alias = "gst_caps_features_contains_id_str")]
405 pub fn contains_by_id(&self, feature: impl AsRef<IdStr>) -> bool {
406 unsafe {
407 cfg_if! {
408 if #[cfg(feature = "v1_26")] {
409 from_glib(ffi::gst_caps_features_contains_id_str(
410 self.as_ptr(),
411 feature.as_ref().as_ptr(),
412 ))
413 } else {
414 from_glib(ffi::gst_caps_features_contains(
415 self.as_ptr(),
416 feature.as_ref().as_gstr().as_ptr(),
417 ))
418 }
419 }
420 }
421 }
422
423 #[deprecated = "use `contains_by_id()` instead"]
424 #[doc(alias = "gst_caps_features_contains_id")]
425 pub fn contains_quark(&self, feature: glib::Quark) -> bool {
426 unsafe {
427 from_glib(ffi::gst_caps_features_contains_id(
428 self.as_ptr(),
429 feature.into_glib(),
430 ))
431 }
432 }
433
434 #[doc(alias = "get_size")]
435 #[doc(alias = "gst_caps_features_get_size")]
436 pub fn size(&self) -> usize {
437 unsafe { ffi::gst_caps_features_get_size(self.as_ptr()) as usize }
438 }
439
440 #[doc(alias = "get_nth")]
441 #[doc(alias = "gst_caps_features_get_nth")]
442 pub fn nth(&self, idx: usize) -> Option<&glib::GStr> {
443 if idx >= self.size() {
444 return None;
445 }
446
447 unsafe {
448 let feature = ffi::gst_caps_features_get_nth(self.as_ptr(), idx as u32);
449 if feature.is_null() {
450 return None;
451 }
452
453 Some(glib::GStr::from_ptr(feature))
454 }
455 }
456
457 #[cfg(feature = "v1_26")]
458 #[doc(alias = "get_nth_by_id")]
459 #[doc(alias = "gst_caps_features_get_nth_id_str")]
460 pub fn nth_id(&self, idx: usize) -> Option<&IdStr> {
461 if idx >= self.size() {
462 return None;
463 }
464
465 unsafe {
466 let feature = ffi::gst_caps_features_get_nth_id_str(self.as_ptr(), idx as u32);
467 if feature.is_null() {
468 return None;
469 }
470
471 Some(&*(feature as *const IdStr))
472 }
473 }
474
475 #[deprecated = "use `nth_by_id()` instead"]
476 #[doc(alias = "gst_caps_features_get_nth_id")]
477 pub fn nth_quark(&self, idx: usize) -> Option<glib::Quark> {
478 if idx >= self.size() {
479 return None;
480 }
481
482 unsafe {
483 let feature = ffi::gst_caps_features_get_nth_id(self.as_ptr(), idx as u32);
484 Some(from_glib(feature))
485 }
486 }
487
488 #[doc(alias = "gst_caps_features_add")]
489 pub fn add(&mut self, feature: impl IntoGStr) {
490 unsafe {
491 feature.run_with_gstr(|feature| {
492 ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ptr())
493 })
494 }
495 }
496
497 #[doc(alias = "gst_caps_features_add_static_str")]
498 pub fn add_from_static(&mut self, feature: impl AsRef<glib::GStr> + 'static) {
499 unsafe {
500 cfg_if! {
501 if #[cfg(feature = "v1_26")] {
502 ffi::gst_caps_features_add_static_str(self.as_mut_ptr(), feature.as_ref().as_ptr())
503 } else {
504 ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ref().as_ptr())
505 }
506 }
507 }
508 }
509
510 #[doc(alias = "gst_caps_features_add_id_str")]
511 pub fn add_from_id(&mut self, feature: impl AsRef<IdStr>) {
512 unsafe {
513 cfg_if! {
514 if #[cfg(feature = "v1_26")] {
515 ffi::gst_caps_features_add_id_str(self.as_mut_ptr(), feature.as_ref().as_ptr())
516 } else {
517 ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ref().as_gstr().as_ptr())
518 }
519 }
520 }
521 }
522
523 #[doc(alias = "gst_caps_features_remove")]
524 pub fn remove(&mut self, feature: impl IntoGStr) {
525 unsafe {
526 feature.run_with_gstr(|feature| {
527 ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.as_ptr())
528 })
529 }
530 }
531
532 #[doc(alias = "gst_caps_features_remove_id_str")]
533 pub fn remove_by_id(&mut self, feature: impl AsRef<IdStr>) {
534 unsafe {
535 cfg_if! {
536 if #[cfg(feature = "v1_26")] {
537 ffi::gst_caps_features_remove_id_str(self.as_mut_ptr(), feature.as_ref().as_ptr())
538 } else {
539 ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.as_ref().as_gstr().as_ptr())
540 }
541 }
542 }
543 }
544
545 #[deprecated = "use `add_by_id()` instead"]
546 #[doc(alias = "gst_caps_features_add_id")]
547 pub fn add_from_quark(&mut self, feature: glib::Quark) {
548 unsafe { ffi::gst_caps_features_add_id(self.as_mut_ptr(), feature.into_glib()) }
549 }
550
551 #[deprecated = "use `remove_by_id()` instead"]
552 #[doc(alias = "gst_caps_features_remove_id")]
553 pub fn remove_by_quark(&mut self, feature: glib::Quark) {
554 unsafe { ffi::gst_caps_features_remove_id(self.as_mut_ptr(), feature.into_glib()) }
555 }
556
557 pub fn iter(&self) -> Iter<'_> {
558 Iter::new(self)
559 }
560
561 #[doc(alias = "gst_caps_features_is_equal")]
563 pub fn is_equal(&self, other: &CapsFeaturesRef) -> bool {
564 unsafe {
565 from_glib(ffi::gst_caps_features_is_equal(
566 self.as_ptr(),
567 other.as_ptr(),
568 ))
569 }
570 }
571}
572
573impl glib::types::StaticType for CapsFeaturesRef {
574 #[inline]
575 fn static_type() -> glib::types::Type {
576 unsafe { from_glib(ffi::gst_structure_get_type()) }
577 }
578}
579
580impl<'a> std::iter::Extend<&'a str> for CapsFeaturesRef {
581 fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) {
582 iter.into_iter().for_each(|f| self.add(f));
583 }
584}
585
586impl<'a> std::iter::Extend<&'a glib::GStr> for CapsFeaturesRef {
587 fn extend<T: IntoIterator<Item = &'a glib::GStr>>(&mut self, iter: T) {
588 iter.into_iter().for_each(|f| self.add(f));
589 }
590}
591
592impl std::iter::Extend<String> for CapsFeaturesRef {
593 fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
594 iter.into_iter().for_each(|f| self.add(&f));
595 }
596}
597
598impl std::iter::Extend<glib::GString> for CapsFeaturesRef {
599 fn extend<T: IntoIterator<Item = glib::GString>>(&mut self, iter: T) {
600 iter.into_iter().for_each(|f| self.add(&f));
601 }
602}
603
604impl<Id: AsRef<IdStr>> std::iter::Extend<Id> for CapsFeaturesRef {
605 fn extend<T: IntoIterator<Item = Id>>(&mut self, iter: T) {
606 iter.into_iter().for_each(|f| self.add_from_id(f));
607 }
608}
609
610impl std::iter::Extend<glib::Quark> for CapsFeaturesRef {
611 #[allow(deprecated)]
612 fn extend<T: IntoIterator<Item = glib::Quark>>(&mut self, iter: T) {
613 iter.into_iter().for_each(|f| self.add_from_quark(f));
614 }
615}
616
617unsafe impl<'a> glib::value::FromValue<'a> for &'a CapsFeaturesRef {
618 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
619
620 unsafe fn from_value(value: &'a glib::Value) -> Self {
621 skip_assert_initialized!();
622 &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const CapsFeaturesRef)
623 }
624}
625
626impl glib::value::ToValue for CapsFeaturesRef {
627 fn to_value(&self) -> glib::Value {
628 let mut value = glib::Value::for_value_type::<CapsFeatures>();
629 unsafe {
630 glib::gobject_ffi::g_value_set_boxed(
631 value.to_glib_none_mut().0,
632 self.as_mut_ptr() as *mut _,
633 )
634 }
635 value
636 }
637
638 fn value_type(&self) -> glib::Type {
639 Self::static_type()
640 }
641}
642
643impl glib::value::ToValueOptional for CapsFeaturesRef {
644 fn to_value_optional(s: Option<&Self>) -> glib::Value {
645 skip_assert_initialized!();
646 let mut value = glib::Value::for_value_type::<CapsFeatures>();
647 unsafe {
648 glib::gobject_ffi::g_value_set_boxed(
649 value.to_glib_none_mut().0,
650 s.map(|s| s.as_mut_ptr()).unwrap_or(ptr::null_mut()) as *mut _,
651 )
652 }
653 value
654 }
655}
656
657crate::utils::define_fixed_size_iter!(
658 Iter,
659 &'a CapsFeaturesRef,
660 &'a glib::GStr,
661 |collection: &CapsFeaturesRef| collection.size(),
662 |collection: &CapsFeaturesRef, idx: usize| unsafe {
663 let feature = ffi::gst_caps_features_get_nth(collection.as_ptr(), idx as u32);
664 glib::GStr::from_ptr(feature)
665 }
666);
667
668impl<'a> IntoIterator for &'a CapsFeaturesRef {
669 type IntoIter = Iter<'a>;
670 type Item = &'a glib::GStr;
671
672 fn into_iter(self) -> Self::IntoIter {
673 self.iter()
674 }
675}
676
677impl<'a> From<&'a str> for CapsFeatures {
678 fn from(value: &'a str) -> Self {
679 skip_assert_initialized!();
680 let mut features = CapsFeatures::new_empty();
681
682 features.add(value);
683
684 features
685 }
686}
687
688impl<'a> From<&'a glib::GStr> for CapsFeatures {
689 fn from(value: &'a glib::GStr) -> Self {
690 skip_assert_initialized!();
691 let mut features = CapsFeatures::new_empty();
692
693 features.add(value);
694
695 features
696 }
697}
698
699impl<Id: AsRef<IdStr>> From<Id> for CapsFeatures {
700 fn from(value: Id) -> Self {
701 skip_assert_initialized!();
702 let mut features = CapsFeatures::new_empty();
703
704 features.add_from_id(value);
705
706 features
707 }
708}
709
710impl From<glib::Quark> for CapsFeatures {
711 #[allow(deprecated)]
712 fn from(value: glib::Quark) -> Self {
713 skip_assert_initialized!();
714 let mut features = CapsFeatures::new_empty();
715
716 features.add_from_quark(value);
717
718 features
719 }
720}
721
722impl<'a, const N: usize> From<[&'a str; N]> for CapsFeatures {
723 fn from(value: [&'a str; N]) -> Self {
724 skip_assert_initialized!();
725 let mut features = CapsFeatures::new_empty();
726
727 value.into_iter().for_each(|f| features.add(f));
728
729 features
730 }
731}
732
733impl<'a, const N: usize> From<[&'a glib::GStr; N]> for CapsFeatures {
734 fn from(value: [&'a glib::GStr; N]) -> Self {
735 skip_assert_initialized!();
736 let mut features = CapsFeatures::new_empty();
737
738 value.into_iter().for_each(|f| features.add(f));
739
740 features
741 }
742}
743
744impl<const N: usize> From<[String; N]> for CapsFeatures {
745 fn from(value: [String; N]) -> Self {
746 skip_assert_initialized!();
747 let mut features = CapsFeatures::new_empty();
748
749 value.into_iter().for_each(|f| features.add(&f));
750
751 features
752 }
753}
754
755impl<const N: usize> From<[glib::GString; N]> for CapsFeatures {
756 fn from(value: [glib::GString; N]) -> Self {
757 skip_assert_initialized!();
758 let mut features = CapsFeatures::new_empty();
759
760 value.into_iter().for_each(|f| features.add(&f));
761
762 features
763 }
764}
765
766impl<const N: usize, Id: AsRef<IdStr>> From<[Id; N]> for CapsFeatures {
767 fn from(value: [Id; N]) -> Self {
768 skip_assert_initialized!();
769 let mut features = CapsFeatures::new_empty();
770
771 value.into_iter().for_each(|f| features.add_from_id(f));
772
773 features
774 }
775}
776
777impl<const N: usize> From<[glib::Quark; N]> for CapsFeatures {
778 #[allow(deprecated)]
779 fn from(value: [glib::Quark; N]) -> Self {
780 skip_assert_initialized!();
781 let mut features = CapsFeatures::new_empty();
782
783 value.into_iter().for_each(|f| features.add_from_quark(f));
784
785 features
786 }
787}
788
789impl<'a> std::iter::FromIterator<&'a str> for CapsFeatures {
790 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
791 skip_assert_initialized!();
792 let mut features = CapsFeatures::new_empty();
793
794 iter.into_iter().for_each(|f| features.add(f));
795
796 features
797 }
798}
799
800impl<'a> std::iter::FromIterator<&'a glib::GStr> for CapsFeatures {
801 fn from_iter<T: IntoIterator<Item = &'a glib::GStr>>(iter: T) -> Self {
802 assert_initialized_main_thread!();
803
804 let mut features = CapsFeatures::new_empty();
805
806 iter.into_iter().for_each(|f| features.add(f));
807
808 features
809 }
810}
811
812impl std::iter::FromIterator<String> for CapsFeatures {
813 fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
814 skip_assert_initialized!();
815 let mut features = CapsFeatures::new_empty();
816
817 iter.into_iter().for_each(|f| features.add(&f));
818
819 features
820 }
821}
822
823impl std::iter::FromIterator<glib::GString> for CapsFeatures {
824 fn from_iter<T: IntoIterator<Item = glib::GString>>(iter: T) -> Self {
825 assert_initialized_main_thread!();
826
827 let mut features = CapsFeatures::new_empty();
828
829 iter.into_iter().for_each(|f| features.add(&f));
830
831 features
832 }
833}
834
835impl<Id: AsRef<IdStr>> std::iter::FromIterator<Id> for CapsFeatures {
836 #[allow(deprecated)]
837 fn from_iter<T: IntoIterator<Item = Id>>(iter: T) -> Self {
838 skip_assert_initialized!();
839 let mut features = CapsFeatures::new_empty();
840
841 iter.into_iter().for_each(|f| features.add_from_id(f));
842
843 features
844 }
845}
846
847impl std::iter::FromIterator<glib::Quark> for CapsFeatures {
848 #[allow(deprecated)]
849 fn from_iter<T: IntoIterator<Item = glib::Quark>>(iter: T) -> Self {
850 skip_assert_initialized!();
851 let mut features = CapsFeatures::new_empty();
852
853 iter.into_iter().for_each(|f| features.add_from_quark(f));
854
855 features
856 }
857}
858
859impl fmt::Debug for CapsFeaturesRef {
860 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
861 f.debug_tuple("CapsFeatures")
862 .field(&self.to_string())
863 .finish()
864 }
865}
866
867impl fmt::Display for CapsFeaturesRef {
868 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
869 let s = unsafe {
870 glib::GString::from_glib_full(ffi::gst_caps_features_to_string(self.as_ptr()))
871 };
872 f.write_str(&s)
873 }
874}
875
876impl ToOwned for CapsFeaturesRef {
877 type Owned = CapsFeatures;
878
879 #[inline]
880 fn to_owned(&self) -> CapsFeatures {
881 unsafe { from_glib_full(ffi::gst_caps_features_copy(self.as_ptr() as *const _) as *mut _) }
882 }
883}
884
885impl std::hash::Hash for CapsFeaturesRef {
886 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
887 use std::hash::{DefaultHasher, Hasher};
888
889 if self.is_any() {
891 "ANY".hash(state);
892 } else if self.is_empty() {
893 "EMPTY".hash(state);
894 } else {
895 let mut features_hash = 0;
896 for f in self.iter() {
897 let mut field_hasher = DefaultHasher::new();
898 f.hash(&mut field_hasher);
899
900 features_hash ^= field_hasher.finish();
901 }
902 features_hash.hash(state);
903 }
904 }
905}
906
907impl std::hash::Hash for CapsFeatures {
908 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
909 self.as_ref().hash(state);
910 }
911}
912
913unsafe impl Sync for CapsFeaturesRef {}
914unsafe impl Send for CapsFeaturesRef {}
915
916pub static CAPS_FEATURE_MEMORY_SYSTEM_MEMORY: &glib::GStr =
917 unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY) };
918pub static CAPS_FEATURES_MEMORY_SYSTEM_MEMORY: LazyLock<CapsFeatures> =
919 LazyLock::new(|| CapsFeatures::new([CAPS_FEATURE_MEMORY_SYSTEM_MEMORY]));
920
921#[cfg(test)]
922mod tests {
923 use super::*;
924 use crate::idstr;
925 use glib::gstr;
926
927 #[test]
928 fn test_from_value_optional() {
929 use glib::value::ToValue;
930
931 crate::init().unwrap();
932
933 let a = None::<CapsFeatures>.to_value();
934 assert!(a.get::<Option<CapsFeatures>>().unwrap().is_none());
935 let b = glib::value::Value::from(&CapsFeatures::new_empty());
936 assert!(b.get::<Option<CapsFeatures>>().unwrap().is_some());
937 }
938
939 #[test]
940 fn trait_impls() {
941 crate::init().unwrap();
942
943 let cf = CapsFeatures::from(gstr!("memory:DMABuf"));
944 assert!(cf.contains(gstr!("memory:DMABuf")));
945
946 let cf = CapsFeatures::from([
947 gstr!("memory:DMABuf"),
948 gstr!("meta:GstVideoOverlayComposition"),
949 ]);
950
951 assert!(cf.contains(gstr!("memory:DMABuf")));
952 assert!(cf.contains("meta:GstVideoOverlayComposition"));
953 assert!(!cf.contains("memory:GLMemory"));
954
955 let cf = CapsFeatures::from_iter(vec![
956 gstr!("memory:DMABuf"),
957 gstr!("meta:GstVideoOverlayComposition"),
958 ]);
959
960 assert!(cf.contains(gstr!("memory:DMABuf")));
961 assert!(cf.contains("meta:GstVideoOverlayComposition"));
962 assert!(!cf.contains("memory:GLMemory"));
963
964 let mut cf = CapsFeatures::new_empty();
965 cf.extend([
966 gstr!("memory:DMABuf"),
967 gstr!("meta:GstVideoOverlayComposition"),
968 ]);
969
970 assert!(cf.contains(gstr!("memory:DMABuf")));
971 assert!(cf.contains("meta:GstVideoOverlayComposition"));
972 assert!(!cf.contains("memory:GLMemory"));
973 }
974
975 #[test]
976 fn trait_impls_from_id() {
977 crate::init().unwrap();
978
979 let cf = CapsFeatures::from(idstr!("memory:DMABuf"));
980 assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
981
982 let cf = CapsFeatures::from([
983 idstr!("memory:DMABuf"),
984 idstr!("meta:GstVideoOverlayComposition"),
985 ]);
986
987 assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
988 assert!(cf.contains("meta:GstVideoOverlayComposition"));
989 assert!(!cf.contains("memory:GLMemory"));
990
991 let cf = CapsFeatures::from_iter(vec![
992 idstr!("memory:DMABuf"),
993 idstr!("meta:GstVideoOverlayComposition"),
994 ]);
995
996 assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
997 assert!(cf.contains("meta:GstVideoOverlayComposition"));
998 assert!(!cf.contains("memory:GLMemory"));
999
1000 let mut cf = CapsFeatures::new_empty();
1001 cf.extend([
1002 idstr!("memory:DMABuf"),
1003 idstr!("meta:GstVideoOverlayComposition"),
1004 ]);
1005
1006 assert!(cf.contains_by_id(idstr!("memory:DMABuf")));
1007 assert!(cf.contains("meta:GstVideoOverlayComposition"));
1008 assert!(!cf.contains("memory:GLMemory"));
1009 }
1010
1011 #[test]
1012 fn trait_impls_from_ref_id() {
1013 crate::init().unwrap();
1014
1015 let dma_buf = idstr!("memory:DMABuf");
1016 let overlay_comp = idstr!("meta:GstVideoOverlayComposition");
1017
1018 let cf = CapsFeatures::from(&dma_buf);
1019 assert!(cf.contains_by_id(&dma_buf));
1020
1021 let cf = CapsFeatures::from([&dma_buf, &overlay_comp]);
1022
1023 assert!(cf.contains_by_id(&dma_buf));
1024 assert!(cf.contains_by_id(&overlay_comp));
1025 assert!(!cf.contains("memory:GLMemory"));
1026
1027 let cf = CapsFeatures::from_iter(vec![&dma_buf, &overlay_comp]);
1028
1029 assert!(cf.contains_by_id(&dma_buf));
1030 assert!(cf.contains_by_id(&overlay_comp));
1031 assert!(!cf.contains("memory:GLMemory"));
1032
1033 let mut cf = CapsFeatures::new_empty();
1034 cf.extend([&dma_buf, &overlay_comp]);
1035
1036 assert!(cf.contains_by_id(dma_buf));
1037 assert!(cf.contains_by_id(overlay_comp));
1038 assert!(!cf.contains("memory:GLMemory"));
1039 }
1040
1041 #[test]
1042 fn test_hash() {
1043 crate::init().unwrap();
1044
1045 use std::hash::BuildHasher;
1046 let bh = std::hash::RandomState::new();
1047
1048 let any = CapsFeatures::new_any();
1049 let empty = CapsFeatures::new_empty();
1050 assert_eq!(bh.hash_one(&any), bh.hash_one(&any));
1051 assert_eq!(bh.hash_one(&empty), bh.hash_one(&empty));
1052 assert_ne!(bh.hash_one(&any), bh.hash_one(&empty));
1053
1054 let cf1 = CapsFeatures::from(gstr!("memory:DMABuf"));
1056 let cf2 = CapsFeatures::from(gstr!("memory:GLMemory"));
1057 assert_eq!(bh.hash_one(&cf1), bh.hash_one(&cf1));
1058 assert_eq!(bh.hash_one(&cf2), bh.hash_one(&cf2));
1059 assert_ne!(bh.hash_one(&cf1), bh.hash_one(&cf2));
1060
1061 let cf1 = CapsFeatures::from([
1063 gstr!("memory:DMABuf"),
1064 gstr!("meta:GstVideoOverlayComposition"),
1065 ]);
1066 let cf2 = CapsFeatures::from([
1067 gstr!("meta:GstVideoOverlayComposition"),
1068 gstr!("memory:DMABuf"),
1069 ]);
1070 assert_eq!(bh.hash_one(&cf1), bh.hash_one(&cf1));
1071 assert_eq!(bh.hash_one(&cf2), bh.hash_one(&cf2));
1072 assert_eq!(bh.hash_one(&cf1), bh.hash_one(&cf2));
1073 }
1074}