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