gstreamer/
caps_features.rs

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