Skip to main content

gstreamer/
caps.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, marker::PhantomData, ptr, str};
4
5use cfg_if::cfg_if;
6use glib::{
7    GStr,
8    prelude::*,
9    translate::*,
10    value::{SendValue, ToSendValue},
11};
12
13use crate::{CapsIntersectMode, IdStr, caps_features::*, ffi, structure::*};
14
15mini_object_wrapper!(Caps, CapsRef, ffi::GstCaps, || { ffi::gst_caps_get_type() });
16
17impl Caps {
18    #[doc(alias = "gst_caps_new_simple")]
19    pub fn builder(name: impl IntoGStr) -> Builder<NoFeature> {
20        assert_initialized_main_thread!();
21        Builder::new(name)
22    }
23
24    #[doc(alias = "gst_caps_new_static_str_simple")]
25    pub fn builder_from_static(name: impl AsRef<GStr> + 'static) -> Builder<NoFeature> {
26        assert_initialized_main_thread!();
27        Builder::from_static(name)
28    }
29
30    #[doc(alias = "gst_caps_new_id_str_simple")]
31    pub fn builder_from_id(name: impl AsRef<IdStr>) -> Builder<NoFeature> {
32        assert_initialized_main_thread!();
33        Builder::from_id(name)
34    }
35
36    #[doc(alias = "gst_caps_new_full")]
37    pub fn builder_full() -> BuilderFull<SomeFeatures> {
38        assert_initialized_main_thread!();
39        BuilderFull::new()
40    }
41
42    #[doc(alias = "gst_caps_new_full")]
43    pub fn builder_full_with_features(features: CapsFeatures) -> BuilderFull<SomeFeatures> {
44        assert_initialized_main_thread!();
45        BuilderFull::with_features(features)
46    }
47
48    #[doc(alias = "gst_caps_new_full")]
49    pub fn builder_full_with_any_features() -> BuilderFull<AnyFeatures> {
50        assert_initialized_main_thread!();
51        BuilderFull::with_any_features()
52    }
53
54    /// Creates a new [`Caps`][crate::Caps] that is empty. That is, the returned
55    /// [`Caps`][crate::Caps] contains no media formats.
56    /// The [`Caps`][crate::Caps] is guaranteed to be writable.
57    ///
58    /// # Returns
59    ///
60    /// the new [`Caps`][crate::Caps]
61    #[doc(alias = "gst_caps_new_empty")]
62    pub fn new_empty() -> Self {
63        assert_initialized_main_thread!();
64        unsafe { from_glib_full(ffi::gst_caps_new_empty()) }
65    }
66
67    /// Creates a new [`Caps`][crate::Caps] that indicates that it is compatible with
68    /// any media format.
69    ///
70    /// # Returns
71    ///
72    /// the new [`Caps`][crate::Caps]
73    #[doc(alias = "gst_caps_new_any")]
74    pub fn new_any() -> Self {
75        assert_initialized_main_thread!();
76        unsafe { from_glib_full(ffi::gst_caps_new_any()) }
77    }
78
79    /// Creates a new [`Caps`][crate::Caps] that contains one [`Structure`][crate::Structure] with name
80    /// `media_type`.
81    /// ## `media_type`
82    /// the media type of the structure
83    ///
84    /// # Returns
85    ///
86    /// the new [`Caps`][crate::Caps]
87    #[doc(alias = "gst_caps_new_empty_simple")]
88    pub fn new_empty_simple(name: impl IntoGStr) -> Self {
89        skip_assert_initialized!();
90        let mut caps = Caps::new_empty();
91
92        let structure = Structure::new_empty(name);
93        caps.get_mut().unwrap().append_structure(structure);
94
95        caps
96    }
97
98    #[doc(alias = "gst_caps_new_static_str_empty_simple")]
99    pub fn new_empty_simple_from_static(name: impl AsRef<GStr> + 'static) -> Self {
100        skip_assert_initialized!();
101        let mut caps = Caps::new_empty();
102
103        let structure = Structure::new_empty_from_static(name);
104        caps.get_mut().unwrap().append_structure(structure);
105
106        caps
107    }
108
109    #[doc(alias = "gst_caps_new_id_str_empty_simple")]
110    pub fn new_empty_simple_from_id(name: impl AsRef<IdStr>) -> Self {
111        skip_assert_initialized!();
112        let mut caps = Caps::new_empty();
113
114        let structure = Structure::new_empty_from_id(name);
115        caps.get_mut().unwrap().append_structure(structure);
116
117        caps
118    }
119
120    /// Modifies the given `self` into a representation with only fixed
121    /// values. First the caps will be truncated and then the first structure will be
122    /// fixated with `gst_structure_fixate()`.
123    ///
124    /// This function takes ownership of `self` and will call [`make_writable()`][Self::make_writable()]
125    /// on it so you must not use `self` afterwards unless you keep an additional
126    /// reference to it with `gst_caps_ref()`.
127    ///
128    /// Note that it is not guaranteed that the returned caps have exactly one
129    /// structure. If `self` are empty caps then the returned caps will be
130    /// the empty too and contain no structure at all.
131    ///
132    /// Calling this function with ANY caps is not allowed.
133    ///
134    /// # Returns
135    ///
136    /// the fixated caps
137    #[doc(alias = "gst_caps_fixate")]
138    pub fn fixate(&mut self) {
139        unsafe {
140            // See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/388
141            assert!(!self.is_any());
142            let ptr = if self.is_empty() {
143                ffi::gst_caps_new_empty()
144            } else {
145                ffi::gst_caps_fixate(self.as_mut_ptr())
146            };
147            self.replace_ptr(ptr);
148        }
149    }
150
151    /// Appends the structures contained in `caps2` to `self` if they are not yet
152    /// expressed by `self`. The structures in `caps2` are not copied -- they are
153    /// transferred to a writable copy of `self`, and then `caps2` is freed.
154    /// If either caps is ANY, the resulting caps will be ANY.
155    /// ## `caps2`
156    /// the [`Caps`][crate::Caps] to merge in
157    ///
158    /// # Returns
159    ///
160    /// the merged caps.
161    #[doc(alias = "gst_caps_merge")]
162    pub fn merge(&mut self, other: Self) {
163        unsafe {
164            let ptr = ffi::gst_caps_merge(self.as_mut_ptr(), other.into_glib_ptr());
165            self.replace_ptr(ptr);
166        }
167    }
168
169    /// Appends `structure` to `self` if it is not already expressed by `self`.
170    /// ## `structure`
171    /// the [`Structure`][crate::Structure] to merge
172    ///
173    /// # Returns
174    ///
175    /// the merged caps.
176    #[doc(alias = "gst_caps_merge_structure")]
177    pub fn merge_structure(&mut self, structure: Structure) {
178        unsafe {
179            let ptr = ffi::gst_caps_merge_structure(self.as_mut_ptr(), structure.into_glib_ptr());
180            self.replace_ptr(ptr);
181        }
182    }
183
184    /// Appends `structure` with `features` to `self` if its not already expressed by `self`.
185    /// ## `structure`
186    /// the [`Structure`][crate::Structure] to merge
187    /// ## `features`
188    /// the [`CapsFeatures`][crate::CapsFeatures] to merge
189    ///
190    /// # Returns
191    ///
192    /// the merged caps.
193    #[doc(alias = "gst_caps_merge_structure_full")]
194    pub fn merge_structure_full(&mut self, structure: Structure, features: Option<CapsFeatures>) {
195        unsafe {
196            let ptr = ffi::gst_caps_merge_structure_full(
197                self.as_mut_ptr(),
198                structure.into_glib_ptr(),
199                features
200                    .map(|f| f.into_glib_ptr())
201                    .unwrap_or(ptr::null_mut()),
202            );
203            self.replace_ptr(ptr);
204        }
205    }
206
207    /// Returns a [`Caps`][crate::Caps] that represents the same set of formats as
208    /// `self`, but contains no lists. Each list is expanded into separate
209    /// [`Structure`][crate::Structure].
210    ///
211    /// This function takes ownership of `self` and will call [`make_writable()`][Self::make_writable()]
212    /// on it so you must not use `self` afterwards unless you keep an additional
213    /// reference to it with `gst_caps_ref()`.
214    ///
215    /// # Returns
216    ///
217    /// the normalized [`Caps`][crate::Caps]
218    #[doc(alias = "gst_caps_normalize")]
219    pub fn normalize(&mut self) {
220        unsafe {
221            let ptr = ffi::gst_caps_normalize(self.as_mut_ptr());
222            self.replace_ptr(ptr);
223        }
224    }
225
226    /// Converts the given `self` into a representation that represents the
227    /// same set of formats, but in a simpler form. Component structures that are
228    /// identical are merged. Component structures that have values that can be
229    /// merged are also merged.
230    ///
231    /// This function takes ownership of `self` and will call [`make_writable()`][Self::make_writable()]
232    /// on it if necessary, so you must not use `self` afterwards unless you keep an
233    /// additional reference to it with `gst_caps_ref()`.
234    ///
235    /// This method does not preserve the original order of `self`.
236    ///
237    /// # Returns
238    ///
239    /// The simplified caps.
240    #[doc(alias = "gst_caps_simplify")]
241    pub fn simplify(&mut self) {
242        unsafe {
243            let ptr = ffi::gst_caps_simplify(self.as_mut_ptr());
244            self.replace_ptr(ptr);
245        }
246    }
247
248    /// Discards all but the first structure from `self`. Useful when
249    /// fixating.
250    ///
251    /// This function takes ownership of `self` and will call [`make_writable()`][Self::make_writable()]
252    /// on it if necessary, so you must not use `self` afterwards unless you keep an
253    /// additional reference to it with `gst_caps_ref()`.
254    ///
255    /// Note that it is not guaranteed that the returned caps have exactly one
256    /// structure. If `self` is any or empty caps then the returned caps will be
257    /// the same and contain no structure at all.
258    ///
259    /// # Returns
260    ///
261    /// truncated caps
262    #[doc(alias = "gst_caps_truncate")]
263    pub fn truncate(&mut self) {
264        unsafe {
265            let ptr = ffi::gst_caps_truncate(self.as_mut_ptr());
266            self.replace_ptr(ptr);
267        }
268    }
269}
270
271impl str::FromStr for Caps {
272    type Err = glib::BoolError;
273
274    #[doc(alias = "gst_caps_from_string")]
275    fn from_str(s: &str) -> Result<Self, Self::Err> {
276        assert_initialized_main_thread!();
277        unsafe {
278            s.run_with_gstr(|s| {
279                Option::<_>::from_glib_full(ffi::gst_caps_from_string(s.as_ptr()))
280                    .ok_or_else(|| glib::bool_error!("Failed to parse caps from string"))
281            })
282        }
283    }
284}
285
286impl From<Structure> for Caps {
287    fn from(v: Structure) -> Caps {
288        skip_assert_initialized!();
289        let mut caps = Caps::new_empty();
290
291        {
292            let caps = caps.get_mut().unwrap();
293            caps.append_structure(v);
294        }
295
296        caps
297    }
298}
299
300impl<const N: usize> From<[Structure; N]> for Caps {
301    fn from(v: [Structure; N]) -> Caps {
302        skip_assert_initialized!();
303        let mut caps = Caps::new_empty();
304
305        {
306            let caps = caps.get_mut().unwrap();
307            v.into_iter().for_each(|s| caps.append_structure(s));
308        }
309
310        caps
311    }
312}
313
314impl From<(Structure, CapsFeatures)> for Caps {
315    fn from(v: (Structure, CapsFeatures)) -> Caps {
316        skip_assert_initialized!();
317        let mut caps = Caps::new_empty();
318
319        {
320            let caps = caps.get_mut().unwrap();
321            caps.append_structure_full(v.0, Some(v.1));
322        }
323
324        caps
325    }
326}
327
328impl<const N: usize> From<[(Structure, CapsFeatures); N]> for Caps {
329    fn from(v: [(Structure, CapsFeatures); N]) -> Caps {
330        skip_assert_initialized!();
331        let mut caps = Caps::new_empty();
332
333        {
334            let caps = caps.get_mut().unwrap();
335            v.into_iter()
336                .for_each(|s| caps.append_structure_full(s.0, Some(s.1)));
337        }
338
339        caps
340    }
341}
342
343impl<const N: usize> From<[(Structure, Option<CapsFeatures>); N]> for Caps {
344    fn from(v: [(Structure, Option<CapsFeatures>); N]) -> Caps {
345        skip_assert_initialized!();
346        let mut caps = Caps::new_empty();
347
348        {
349            let caps = caps.get_mut().unwrap();
350            v.into_iter()
351                .for_each(|s| caps.append_structure_full(s.0, s.1));
352        }
353
354        caps
355    }
356}
357
358impl std::iter::FromIterator<Structure> for Caps {
359    fn from_iter<T: IntoIterator<Item = Structure>>(iter: T) -> Self {
360        skip_assert_initialized!();
361        let mut caps = Caps::new_empty();
362
363        {
364            let caps = caps.get_mut().unwrap();
365            iter.into_iter().for_each(|s| caps.append_structure(s));
366        }
367
368        caps
369    }
370}
371
372impl std::iter::FromIterator<(Structure, CapsFeatures)> for Caps {
373    fn from_iter<T: IntoIterator<Item = (Structure, CapsFeatures)>>(iter: T) -> Self {
374        skip_assert_initialized!();
375        let mut caps = Caps::new_empty();
376
377        {
378            let caps = caps.get_mut().unwrap();
379            iter.into_iter()
380                .for_each(|(s, f)| caps.append_structure_full(s, Some(f)));
381        }
382
383        caps
384    }
385}
386
387impl std::iter::FromIterator<(Structure, Option<CapsFeatures>)> for Caps {
388    fn from_iter<T: IntoIterator<Item = (Structure, Option<CapsFeatures>)>>(iter: T) -> Self {
389        skip_assert_initialized!();
390        let mut caps = Caps::new_empty();
391
392        {
393            let caps = caps.get_mut().unwrap();
394            iter.into_iter()
395                .for_each(|(s, f)| caps.append_structure_full(s, f));
396        }
397
398        caps
399    }
400}
401
402impl std::iter::FromIterator<Caps> for Caps {
403    fn from_iter<T: IntoIterator<Item = Caps>>(iter: T) -> Self {
404        skip_assert_initialized!();
405        let mut caps = Caps::new_empty();
406
407        {
408            let caps = caps.get_mut().unwrap();
409            iter.into_iter()
410                .for_each(|other_caps| caps.append(other_caps));
411        }
412
413        caps
414    }
415}
416
417impl std::iter::Extend<Structure> for CapsRef {
418    fn extend<T: IntoIterator<Item = Structure>>(&mut self, iter: T) {
419        iter.into_iter().for_each(|s| self.append_structure(s));
420    }
421}
422
423impl std::iter::Extend<(Structure, CapsFeatures)> for CapsRef {
424    fn extend<T: IntoIterator<Item = (Structure, CapsFeatures)>>(&mut self, iter: T) {
425        iter.into_iter()
426            .for_each(|(s, f)| self.append_structure_full(s, Some(f)));
427    }
428}
429
430impl std::iter::Extend<(Structure, Option<CapsFeatures>)> for CapsRef {
431    fn extend<T: IntoIterator<Item = (Structure, Option<CapsFeatures>)>>(&mut self, iter: T) {
432        iter.into_iter()
433            .for_each(|(s, f)| self.append_structure_full(s, f));
434    }
435}
436
437impl std::iter::Extend<Caps> for CapsRef {
438    fn extend<T: IntoIterator<Item = Caps>>(&mut self, iter: T) {
439        iter.into_iter().for_each(|caps| self.append(caps));
440    }
441}
442
443impl CapsRef {
444    // rustdoc-stripper-ignore-next
445    /// Sets field `name` to the given value `value`.
446    ///
447    /// Overrides any default or previously defined value for `name`.
448    #[doc(alias = "gst_caps_set_value")]
449    #[doc(alias = "gst_caps_set_simple")]
450    pub fn set(&mut self, name: impl IntoGStr, value: impl ToSendValue + Sync) {
451        let value = value.to_send_value();
452        self.set_value(name, value);
453    }
454
455    // rustdoc-stripper-ignore-next
456    /// Sets field `name` to the given value `value`.
457    ///
458    /// Overrides any default or previously defined value for `name`.
459    #[doc(alias = "gst_caps_set_value_static_str")]
460    #[doc(alias = "gst_caps_set_simple_static_str")]
461    pub fn set_with_static(
462        &mut self,
463        name: impl AsRef<GStr> + 'static,
464        value: impl ToSendValue + Sync,
465    ) {
466        let value = value.to_send_value();
467        self.set_value_with_static(name, value);
468    }
469
470    // rustdoc-stripper-ignore-next
471    /// Sets field `name` to the given value `value`.
472    ///
473    /// Overrides any default or previously defined value for `name`.
474    #[doc(alias = "gst_caps_id_str_set_value")]
475    #[doc(alias = "gst_caps_id_str_set_simple")]
476    pub fn set_with_id(&mut self, name: impl AsRef<IdStr>, value: impl ToSendValue + Sync) {
477        let value = value.to_send_value();
478        self.set_value_with_id(name, value);
479    }
480
481    // rustdoc-stripper-ignore-next
482    /// Sets field `name` to the given value if the `predicate` evaluates to `true`.
483    ///
484    /// This has no effect if the `predicate` evaluates to `false`,
485    /// i.e. default or previous value for `name` is kept.
486    #[doc(alias = "gst_caps_set_value")]
487    #[doc(alias = "gst_caps_set_simple")]
488    pub fn set_if(&mut self, name: impl IntoGStr, value: impl ToSendValue + Sync, predicate: bool) {
489        if predicate {
490            self.set(name, value);
491        }
492    }
493
494    // rustdoc-stripper-ignore-next
495    /// Sets field `name` to the given value if the `predicate` evaluates to `true`.
496    ///
497    /// This has no effect if the `predicate` evaluates to `false`,
498    /// i.e. default or previous value for `name` is kept.
499    #[doc(alias = "gst_caps_set_value_static_str")]
500    #[doc(alias = "gst_caps_set_simple_static_str")]
501    pub fn set_with_static_if(
502        &mut self,
503        name: impl AsRef<GStr> + 'static,
504        value: impl ToSendValue + Sync,
505        predicate: bool,
506    ) {
507        if predicate {
508            self.set_with_static(name, value);
509        }
510    }
511
512    // rustdoc-stripper-ignore-next
513    /// Sets field `name` to the given value if the `predicate` evaluates to `true`.
514    ///
515    /// This has no effect if the `predicate` evaluates to `false`,
516    /// i.e. default or previous value for `name` is kept.
517    #[doc(alias = "gst_caps_id_str_set_value")]
518    #[doc(alias = "gst_caps_id_str_set_simple")]
519    pub fn set_with_id_if(
520        &mut self,
521        name: impl AsRef<IdStr>,
522        value: impl ToSendValue + Sync,
523        predicate: bool,
524    ) {
525        if predicate {
526            self.set_with_id(name, value);
527        }
528    }
529
530    // rustdoc-stripper-ignore-next
531    /// Sets field `name` to the given inner value if `value` is `Some`.
532    ///
533    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
534    #[doc(alias = "gst_caps_set_value")]
535    #[doc(alias = "gst_caps_set_simple")]
536    pub fn set_if_some(&mut self, name: impl IntoGStr, value: Option<impl ToSendValue + Sync>) {
537        if let Some(value) = value {
538            self.set(name, value);
539        }
540    }
541
542    // rustdoc-stripper-ignore-next
543    /// Sets field `name` to the given inner value if `value` is `Some`.
544    ///
545    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
546    #[doc(alias = "gst_caps_set_value_static_str")]
547    #[doc(alias = "gst_caps_set_simple_static_str")]
548    pub fn set_with_static_if_some(
549        &mut self,
550        name: impl AsRef<GStr> + 'static,
551        value: Option<impl ToSendValue + Sync>,
552    ) {
553        if let Some(value) = value {
554            self.set_with_static(name, value);
555        }
556    }
557
558    // rustdoc-stripper-ignore-next
559    /// Sets field `name` to the given inner value if `value` is `Some`.
560    ///
561    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
562    #[doc(alias = "gst_caps_id_str_set_value")]
563    #[doc(alias = "gst_caps_id_str_set_simple")]
564    pub fn set_with_id_if_some(
565        &mut self,
566        name: impl AsRef<IdStr>,
567        value: Option<impl ToSendValue + Sync>,
568    ) {
569        if let Some(value) = value {
570            self.set_with_id(name, value);
571        }
572    }
573
574    // rustdoc-stripper-ignore-next
575    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
576    ///
577    /// Overrides any default or previously defined value for `name`.
578    #[inline]
579    pub fn set_from_iter<
580        V: ValueType + ToSendValue + FromIterator<SendValue> + Sync,
581        I: ToSendValue,
582    >(
583        &mut self,
584        name: impl IntoGStr,
585        iter: impl IntoIterator<Item = I>,
586    ) {
587        let iter = iter.into_iter().map(|item| item.to_send_value());
588        self.set(name, V::from_iter(iter));
589    }
590
591    // rustdoc-stripper-ignore-next
592    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
593    ///
594    /// Overrides any default or previously defined value for `name`.
595    #[inline]
596    pub fn set_with_static_from_iter<
597        V: ValueType + ToSendValue + FromIterator<SendValue> + Sync,
598        I: ToSendValue,
599    >(
600        &mut self,
601        name: impl AsRef<GStr> + 'static,
602        iter: impl IntoIterator<Item = I>,
603    ) {
604        let iter = iter.into_iter().map(|item| item.to_send_value());
605        self.set_with_static(name, V::from_iter(iter));
606    }
607
608    // rustdoc-stripper-ignore-next
609    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
610    ///
611    /// Overrides any default or previously defined value for `name`.
612    #[inline]
613    pub fn set_with_id_from_iter<
614        V: ValueType + ToSendValue + FromIterator<SendValue> + Sync,
615        I: ToSendValue,
616    >(
617        &mut self,
618        name: impl AsRef<IdStr>,
619        iter: impl IntoIterator<Item = I>,
620    ) {
621        let iter = iter.into_iter().map(|item| item.to_send_value());
622        self.set_with_id(name, V::from_iter(iter));
623    }
624
625    // rustdoc-stripper-ignore-next
626    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
627    /// if `iter` is not empty.
628    ///
629    /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
630    #[inline]
631    pub fn set_if_not_empty<
632        V: ValueType + ToSendValue + FromIterator<SendValue> + Sync,
633        I: ToSendValue,
634    >(
635        &mut self,
636        name: impl IntoGStr,
637        iter: impl IntoIterator<Item = I>,
638    ) {
639        let mut iter = iter.into_iter().peekable();
640        if iter.peek().is_some() {
641            let iter = iter.map(|item| item.to_send_value());
642            self.set(name, V::from_iter(iter));
643        }
644    }
645
646    // rustdoc-stripper-ignore-next
647    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
648    /// if `iter` is not empty.
649    ///
650    /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
651    #[inline]
652    pub fn set_with_static_if_not_empty<
653        V: ValueType + ToSendValue + FromIterator<SendValue> + Sync,
654        I: ToSendValue,
655    >(
656        &mut self,
657        name: impl AsRef<GStr> + 'static,
658        iter: impl IntoIterator<Item = I>,
659    ) {
660        let mut iter = iter.into_iter().peekable();
661        if iter.peek().is_some() {
662            let iter = iter.map(|item| item.to_send_value());
663            self.set_with_static(name, V::from_iter(iter));
664        }
665    }
666
667    // rustdoc-stripper-ignore-next
668    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
669    /// if `iter` is not empty.
670    ///
671    /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
672    #[inline]
673    pub fn set_with_id_if_not_empty<
674        V: ValueType + ToSendValue + FromIterator<SendValue> + Sync,
675        I: ToSendValue,
676    >(
677        &mut self,
678        name: impl AsRef<IdStr>,
679        iter: impl IntoIterator<Item = I>,
680    ) {
681        let mut iter = iter.into_iter().peekable();
682        if iter.peek().is_some() {
683            let iter = iter.map(|item| item.to_send_value());
684            self.set_with_id(name, V::from_iter(iter));
685        }
686    }
687
688    // rustdoc-stripper-ignore-next
689    /// Sets field `name` to the given value `value`.
690    ///
691    /// Overrides any default or previously defined value for `name`.
692    #[doc(alias = "gst_caps_set_value")]
693    pub fn set_value(&mut self, name: impl IntoGStr, value: glib::SendValue) {
694        unsafe {
695            name.run_with_gstr(|name| {
696                ffi::gst_caps_set_value(self.as_mut_ptr(), name.as_ptr(), value.to_glib_none().0)
697            });
698        }
699    }
700
701    // rustdoc-stripper-ignore-next
702    /// Sets field `name` to the given value `value`.
703    ///
704    /// Overrides any default or previously defined value for `name`.
705    #[doc(alias = "gst_caps_set_value_static_str")]
706    pub fn set_value_with_static(
707        &mut self,
708        name: impl AsRef<GStr> + 'static,
709        value: glib::SendValue,
710    ) {
711        unsafe {
712            cfg_if! {
713                if #[cfg(feature = "v1_26")] {
714                    ffi::gst_caps_set_value_static_str(
715                        self.as_mut_ptr(),
716                        name.as_ref().as_ptr(),
717                        value.to_glib_none().0,
718                    )
719                } else {
720                    ffi::gst_caps_set_value(self.as_mut_ptr(), name.as_ref().as_ptr(), value.to_glib_none().0)
721                }
722            }
723        }
724    }
725
726    // rustdoc-stripper-ignore-next
727    /// Sets field `name` to the given value `value`.
728    ///
729    /// Overrides any default or previously defined value for `name`.
730    #[doc(alias = "gst_caps_id_str_set_value")]
731    pub fn set_value_with_id(&mut self, name: impl AsRef<IdStr>, value: glib::SendValue) {
732        unsafe {
733            cfg_if! {
734                if #[cfg(feature = "v1_26")] {
735                    ffi::gst_caps_id_str_set_value(
736                        self.as_mut_ptr(),
737                        name.as_ref().as_ptr(),
738                        value.to_glib_none().0,
739                    )
740                } else {
741                    ffi::gst_caps_set_value(self.as_mut_ptr(), name.as_ref().as_gstr().as_ptr(), value.to_glib_none().0)
742                }
743            }
744        }
745    }
746
747    // rustdoc-stripper-ignore-next
748    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
749    ///
750    /// This has no effect if the `predicate` evaluates to `false`,
751    /// i.e. default or previous value for `name` is kept.
752    #[doc(alias = "gst_caps_set_value")]
753    pub fn set_value_if(&mut self, name: impl IntoGStr, value: SendValue, predicate: bool) {
754        if predicate {
755            self.set_value(name, value);
756        }
757    }
758
759    // rustdoc-stripper-ignore-next
760    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
761    ///
762    /// This has no effect if the `predicate` evaluates to `false`,
763    /// i.e. default or previous value for `name` is kept.
764    #[doc(alias = "gst_caps_set_value_static_str")]
765    pub fn set_value_with_static_if(
766        &mut self,
767        name: impl AsRef<GStr> + 'static,
768        value: SendValue,
769        predicate: bool,
770    ) {
771        if predicate {
772            self.set_value_with_static(name, value);
773        }
774    }
775
776    // rustdoc-stripper-ignore-next
777    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
778    ///
779    /// This has no effect if the `predicate` evaluates to `false`,
780    /// i.e. default or previous value for `name` is kept.
781    #[doc(alias = "gst_caps_id_str_set_value")]
782    pub fn set_value_with_id_if(
783        &mut self,
784        name: impl AsRef<IdStr>,
785        value: SendValue,
786        predicate: bool,
787    ) {
788        if predicate {
789            self.set_value_with_id(name, value);
790        }
791    }
792
793    // rustdoc-stripper-ignore-next
794    /// Sets field `name` to the given inner value if `value` is `Some`.
795    ///
796    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
797    #[doc(alias = "gst_caps_set_value")]
798    pub fn set_value_if_some(&mut self, name: impl IntoGStr, value: Option<SendValue>) {
799        if let Some(value) = value {
800            self.set_value(name, value);
801        }
802    }
803
804    // rustdoc-stripper-ignore-next
805    /// Sets field `name` to the given inner value if `value` is `Some`.
806    ///
807    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
808    #[doc(alias = "gst_caps_set_value_static_str")]
809    pub fn set_value_with_static_if_some(
810        &mut self,
811        name: impl AsRef<GStr> + 'static,
812        value: Option<SendValue>,
813    ) {
814        if let Some(value) = value {
815            self.set_value_with_static(name, value);
816        }
817    }
818
819    // rustdoc-stripper-ignore-next
820    /// Sets field `name` to the given inner value if `value` is `Some`.
821    ///
822    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
823    #[doc(alias = "gst_caps_id_str_set_value")]
824    pub fn set_value_with_id_if_some(&mut self, name: impl AsRef<IdStr>, value: Option<SendValue>) {
825        if let Some(value) = value {
826            self.set_value_with_id(name, value);
827        }
828    }
829
830    #[doc(alias = "get_structure")]
831    #[doc(alias = "gst_caps_get_structure")]
832    pub fn structure(&self, idx: usize) -> Option<&StructureRef> {
833        if idx >= self.size() {
834            return None;
835        }
836
837        unsafe {
838            let structure = ffi::gst_caps_get_structure(self.as_ptr(), idx as u32);
839            if structure.is_null() {
840                return None;
841            }
842
843            Some(StructureRef::from_glib_borrow(structure))
844        }
845    }
846
847    #[doc(alias = "get_mut_structure")]
848    #[doc(alias = "gst_caps_get_structure")]
849    pub fn structure_mut(&mut self, idx: usize) -> Option<&mut StructureRef> {
850        if idx >= self.size() {
851            return None;
852        }
853
854        unsafe {
855            let structure = ffi::gst_caps_get_structure(self.as_ptr(), idx as u32);
856            if structure.is_null() {
857                return None;
858            }
859
860            Some(StructureRef::from_glib_borrow_mut(structure))
861        }
862    }
863
864    #[doc(alias = "get_features")]
865    #[doc(alias = "gst_caps_get_features")]
866    pub fn features(&self, idx: usize) -> Option<&CapsFeaturesRef> {
867        if idx >= self.size() {
868            return None;
869        }
870
871        unsafe {
872            let features = ffi::gst_caps_get_features(self.as_ptr(), idx as u32);
873            Some(CapsFeaturesRef::from_glib_borrow(features))
874        }
875    }
876
877    #[doc(alias = "get_mut_features")]
878    #[doc(alias = "gst_caps_get_features")]
879    pub fn features_mut(&mut self, idx: usize) -> Option<&mut CapsFeaturesRef> {
880        if idx >= self.size() {
881            return None;
882        }
883
884        unsafe {
885            let features = ffi::gst_caps_get_features(self.as_ptr(), idx as u32);
886            Some(CapsFeaturesRef::from_glib_borrow_mut(features))
887        }
888    }
889
890    #[doc(alias = "gst_caps_set_features")]
891    pub fn set_features(&mut self, idx: usize, features: Option<CapsFeatures>) {
892        assert!(idx < self.size());
893
894        unsafe {
895            ffi::gst_caps_set_features(
896                self.as_mut_ptr(),
897                idx as u32,
898                features
899                    .map(|f| f.into_glib_ptr())
900                    .unwrap_or(ptr::null_mut()),
901            )
902        }
903    }
904
905    #[cfg(feature = "v1_16")]
906    #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
907    #[doc(alias = "gst_caps_set_features_simple")]
908    pub fn set_features_simple(&mut self, features: Option<CapsFeatures>) {
909        unsafe {
910            ffi::gst_caps_set_features_simple(
911                self.as_mut_ptr(),
912                features
913                    .map(|f| f.into_glib_ptr())
914                    .unwrap_or(ptr::null_mut()),
915            )
916        }
917    }
918
919    #[doc(alias = "get_size")]
920    #[doc(alias = "gst_caps_get_size")]
921    pub fn size(&self) -> usize {
922        unsafe { ffi::gst_caps_get_size(self.as_ptr()) as usize }
923    }
924
925    pub fn len(&self) -> usize {
926        self.size()
927    }
928
929    pub fn iter(&self) -> Iter<'_> {
930        Iter::new(self)
931    }
932
933    pub fn iter_mut(&mut self) -> IterMut<'_> {
934        IterMut::new(self)
935    }
936
937    pub fn iter_with_features(&self) -> IterFeatures<'_> {
938        IterFeatures::new(self)
939    }
940
941    pub fn iter_with_features_mut(&mut self) -> IterFeaturesMut<'_> {
942        IterFeaturesMut::new(self)
943    }
944
945    #[doc(alias = "gst_caps_append_structure")]
946    pub fn append_structure(&mut self, structure: Structure) {
947        unsafe { ffi::gst_caps_append_structure(self.as_mut_ptr(), structure.into_glib_ptr()) }
948    }
949
950    #[doc(alias = "gst_caps_append_structure_full")]
951    pub fn append_structure_full(&mut self, structure: Structure, features: Option<CapsFeatures>) {
952        unsafe {
953            ffi::gst_caps_append_structure_full(
954                self.as_mut_ptr(),
955                structure.into_glib_ptr(),
956                features
957                    .map(|f| f.into_glib_ptr())
958                    .unwrap_or(ptr::null_mut()),
959            )
960        }
961    }
962
963    #[doc(alias = "gst_caps_remove_structure")]
964    pub fn remove_structure(&mut self, idx: usize) {
965        assert!(idx < self.size());
966
967        unsafe { ffi::gst_caps_remove_structure(self.as_mut_ptr(), idx as u32) }
968    }
969
970    #[doc(alias = "gst_caps_append")]
971    pub fn append(&mut self, other: Caps) {
972        unsafe { ffi::gst_caps_append(self.as_mut_ptr(), other.into_glib_ptr()) }
973    }
974
975    #[doc(alias = "gst_caps_can_intersect")]
976    pub fn can_intersect(&self, other: &Self) -> bool {
977        unsafe { from_glib(ffi::gst_caps_can_intersect(self.as_ptr(), other.as_ptr())) }
978    }
979
980    #[doc(alias = "gst_caps_intersect")]
981    pub fn intersect(&self, other: &Self) -> Caps {
982        unsafe {
983            from_glib_full(ffi::gst_caps_intersect(
984                self.as_mut_ptr(),
985                other.as_mut_ptr(),
986            ))
987        }
988    }
989
990    #[doc(alias = "gst_caps_intersect_full")]
991    pub fn intersect_with_mode(&self, other: &Self, mode: CapsIntersectMode) -> Caps {
992        unsafe {
993            from_glib_full(ffi::gst_caps_intersect_full(
994                self.as_mut_ptr(),
995                other.as_mut_ptr(),
996                mode.into_glib(),
997            ))
998        }
999    }
1000
1001    #[doc(alias = "gst_caps_is_always_compatible")]
1002    pub fn is_always_compatible(&self, other: &Self) -> bool {
1003        unsafe {
1004            from_glib(ffi::gst_caps_is_always_compatible(
1005                self.as_ptr(),
1006                other.as_ptr(),
1007            ))
1008        }
1009    }
1010
1011    #[doc(alias = "gst_caps_is_any")]
1012    pub fn is_any(&self) -> bool {
1013        unsafe { from_glib(ffi::gst_caps_is_any(self.as_ptr())) }
1014    }
1015
1016    #[doc(alias = "gst_caps_is_empty")]
1017    pub fn is_empty(&self) -> bool {
1018        unsafe { from_glib(ffi::gst_caps_is_empty(self.as_ptr())) }
1019    }
1020
1021    #[doc(alias = "gst_caps_is_fixed")]
1022    pub fn is_fixed(&self) -> bool {
1023        unsafe { from_glib(ffi::gst_caps_is_fixed(self.as_ptr())) }
1024    }
1025
1026    #[doc(alias = "gst_caps_is_equal_fixed")]
1027    pub fn is_equal_fixed(&self, other: &Self) -> bool {
1028        unsafe { from_glib(ffi::gst_caps_is_equal_fixed(self.as_ptr(), other.as_ptr())) }
1029    }
1030
1031    #[doc(alias = "gst_caps_is_strictly_equal")]
1032    pub fn is_strictly_equal(&self, other: &Self) -> bool {
1033        unsafe {
1034            from_glib(ffi::gst_caps_is_strictly_equal(
1035                self.as_ptr(),
1036                other.as_ptr(),
1037            ))
1038        }
1039    }
1040
1041    #[doc(alias = "gst_caps_is_subset")]
1042    pub fn is_subset(&self, superset: &Self) -> bool {
1043        unsafe { from_glib(ffi::gst_caps_is_subset(self.as_ptr(), superset.as_ptr())) }
1044    }
1045
1046    #[doc(alias = "gst_caps_is_subset_structure")]
1047    pub fn is_subset_structure(&self, structure: &StructureRef) -> bool {
1048        unsafe {
1049            from_glib(ffi::gst_caps_is_subset_structure(
1050                self.as_ptr(),
1051                structure.as_ptr(),
1052            ))
1053        }
1054    }
1055
1056    #[doc(alias = "gst_caps_is_subset_structure_full")]
1057    pub fn is_subset_structure_full(
1058        &self,
1059        structure: &StructureRef,
1060        features: Option<&CapsFeaturesRef>,
1061    ) -> bool {
1062        unsafe {
1063            from_glib(ffi::gst_caps_is_subset_structure_full(
1064                self.as_ptr(),
1065                structure.as_ptr(),
1066                features.map(|f| f.as_ptr()).unwrap_or(ptr::null()),
1067            ))
1068        }
1069    }
1070
1071    #[doc(alias = "gst_caps_subtract")]
1072    pub fn subtract(&self, other: &Self) -> Caps {
1073        unsafe {
1074            from_glib_full(ffi::gst_caps_subtract(
1075                self.as_mut_ptr(),
1076                other.as_mut_ptr(),
1077            ))
1078        }
1079    }
1080
1081    #[cfg(feature = "v1_20")]
1082    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
1083    #[doc(alias = "gst_caps_serialize")]
1084    pub fn serialize(&self, flags: crate::SerializeFlags) -> glib::GString {
1085        unsafe { from_glib_full(ffi::gst_caps_serialize(&self.0, flags.into_glib())) }
1086    }
1087
1088    #[doc(alias = "gst_caps_foreach")]
1089    pub fn foreach<F: FnMut(&CapsFeaturesRef, &StructureRef) -> std::ops::ControlFlow<()>>(
1090        &self,
1091        mut func: F,
1092    ) -> bool {
1093        unsafe {
1094            unsafe extern "C" fn trampoline<
1095                F: FnMut(&CapsFeaturesRef, &StructureRef) -> std::ops::ControlFlow<()>,
1096            >(
1097                features: *mut ffi::GstCapsFeatures,
1098                s: *mut ffi::GstStructure,
1099                user_data: glib::ffi::gpointer,
1100            ) -> glib::ffi::gboolean {
1101                unsafe {
1102                    let func = &mut *(user_data as *mut F);
1103                    let res = func(
1104                        CapsFeaturesRef::from_glib_borrow(features),
1105                        StructureRef::from_glib_borrow(s),
1106                    );
1107
1108                    matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1109                }
1110            }
1111            let func = &mut func as *mut F;
1112            from_glib(ffi::gst_caps_foreach(
1113                self.as_ptr(),
1114                Some(trampoline::<F>),
1115                func as glib::ffi::gpointer,
1116            ))
1117        }
1118    }
1119
1120    #[doc(alias = "gst_caps_map_in_place")]
1121    pub fn map_in_place<
1122        F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> std::ops::ControlFlow<()>,
1123    >(
1124        &mut self,
1125        mut func: F,
1126    ) {
1127        unsafe {
1128            unsafe extern "C" fn trampoline<
1129                F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> std::ops::ControlFlow<()>,
1130            >(
1131                features: *mut ffi::GstCapsFeatures,
1132                s: *mut ffi::GstStructure,
1133                user_data: glib::ffi::gpointer,
1134            ) -> glib::ffi::gboolean {
1135                unsafe {
1136                    let func = &mut *(user_data as *mut F);
1137                    let res = func(
1138                        CapsFeaturesRef::from_glib_borrow_mut(features),
1139                        StructureRef::from_glib_borrow_mut(s),
1140                    );
1141
1142                    matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1143                }
1144            }
1145            let func = &mut func as *mut F;
1146            let _ = ffi::gst_caps_map_in_place(
1147                self.as_mut_ptr(),
1148                Some(trampoline::<F>),
1149                func as glib::ffi::gpointer,
1150            );
1151        }
1152    }
1153
1154    #[doc(alias = "gst_caps_filter_and_map_in_place")]
1155    pub fn filter_map_in_place<
1156        F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> CapsFilterMapAction,
1157    >(
1158        &mut self,
1159        mut func: F,
1160    ) {
1161        unsafe {
1162            unsafe extern "C" fn trampoline<
1163                F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> CapsFilterMapAction,
1164            >(
1165                features: *mut ffi::GstCapsFeatures,
1166                s: *mut ffi::GstStructure,
1167                user_data: glib::ffi::gpointer,
1168            ) -> glib::ffi::gboolean {
1169                unsafe {
1170                    let func = &mut *(user_data as *mut F);
1171
1172                    let res = func(
1173                        CapsFeaturesRef::from_glib_borrow_mut(features),
1174                        StructureRef::from_glib_borrow_mut(s),
1175                    );
1176
1177                    match res {
1178                        CapsFilterMapAction::Keep => glib::ffi::GTRUE,
1179                        CapsFilterMapAction::Remove => glib::ffi::GFALSE,
1180                    }
1181                }
1182            }
1183
1184            let func = &mut func as *mut F;
1185            ffi::gst_caps_filter_and_map_in_place(
1186                self.as_mut_ptr(),
1187                Some(trampoline::<F>),
1188                func as glib::ffi::gpointer,
1189            );
1190        }
1191    }
1192}
1193
1194#[derive(Debug)]
1195pub enum CapsFilterMapAction {
1196    Keep,
1197    Remove,
1198}
1199
1200macro_rules! define_iter(
1201    ($name:ident, $typ:ty, $styp:ty, $get_item:expr) => {
1202        crate::utils::define_fixed_size_iter!(
1203            $name, $typ, $styp,
1204            |collection: &CapsRef| collection.size(),
1205            $get_item
1206        );
1207    }
1208);
1209
1210define_iter!(
1211    Iter,
1212    &'a CapsRef,
1213    &'a StructureRef,
1214    |caps: &CapsRef, idx| unsafe {
1215        let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32);
1216        StructureRef::from_glib_borrow(ptr as *const ffi::GstStructure)
1217    }
1218);
1219define_iter!(
1220    IterMut,
1221    &'a mut CapsRef,
1222    &'a mut StructureRef,
1223    |caps: &mut CapsRef, idx| unsafe {
1224        let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32);
1225        StructureRef::from_glib_borrow_mut(ptr)
1226    }
1227);
1228define_iter!(
1229    IterFeatures,
1230    &'a CapsRef,
1231    (&'a StructureRef, &'a CapsFeaturesRef),
1232    |caps: &CapsRef, idx| unsafe {
1233        let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32);
1234        let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx as u32);
1235        (
1236            StructureRef::from_glib_borrow(ptr1),
1237            CapsFeaturesRef::from_glib_borrow(ptr2),
1238        )
1239    }
1240);
1241define_iter!(
1242    IterFeaturesMut,
1243    &'a mut CapsRef,
1244    (&'a mut StructureRef, &'a mut CapsFeaturesRef),
1245    |caps: &mut CapsRef, idx| unsafe {
1246        let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32);
1247        let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx as u32);
1248        (
1249            StructureRef::from_glib_borrow_mut(ptr1),
1250            CapsFeaturesRef::from_glib_borrow_mut(ptr2),
1251        )
1252    }
1253);
1254
1255impl<'a> IntoIterator for &'a CapsRef {
1256    type IntoIter = IterFeatures<'a>;
1257    type Item = (&'a StructureRef, &'a CapsFeaturesRef);
1258
1259    fn into_iter(self) -> Self::IntoIter {
1260        self.iter_with_features()
1261    }
1262}
1263
1264impl<'a> IntoIterator for &'a mut CapsRef {
1265    type IntoIter = IterFeaturesMut<'a>;
1266    type Item = (&'a mut StructureRef, &'a mut CapsFeaturesRef);
1267
1268    fn into_iter(self) -> Self::IntoIter {
1269        self.iter_with_features_mut()
1270    }
1271}
1272
1273impl fmt::Debug for Caps {
1274    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1275        <CapsRef as fmt::Debug>::fmt(self, f)
1276    }
1277}
1278
1279impl fmt::Display for Caps {
1280    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1281        <CapsRef as fmt::Display>::fmt(self, f)
1282    }
1283}
1284
1285impl PartialEq for Caps {
1286    fn eq(&self, other: &Caps) -> bool {
1287        CapsRef::eq(self, other)
1288    }
1289}
1290
1291impl Eq for Caps {}
1292
1293impl PartialEq<CapsRef> for Caps {
1294    fn eq(&self, other: &CapsRef) -> bool {
1295        CapsRef::eq(self, other)
1296    }
1297}
1298
1299impl PartialEq<Caps> for CapsRef {
1300    fn eq(&self, other: &Caps) -> bool {
1301        CapsRef::eq(other, self)
1302    }
1303}
1304
1305impl fmt::Debug for CapsRef {
1306    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1307        if self.is_any() {
1308            f.debug_tuple("Caps(\"ANY\")").finish()
1309        } else if self.is_empty() {
1310            f.debug_tuple("Caps(\"EMPTY\")").finish()
1311        } else {
1312            let mut debug = f.debug_tuple("Caps");
1313
1314            for (structure, features) in self.iter_with_features() {
1315                struct WithFeatures<'a> {
1316                    features: &'a CapsFeaturesRef,
1317                    structure: &'a StructureRef,
1318                }
1319
1320                impl fmt::Debug for WithFeatures<'_> {
1321                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1322                        let name = format!("{}({})", self.structure.name(), self.features);
1323                        let mut debug = f.debug_struct(&name);
1324
1325                        for (id, field) in self.structure.iter() {
1326                            if field.type_() == Structure::static_type() {
1327                                let s = field.get::<Structure>().unwrap();
1328                                debug.field(id, &s);
1329                            } else if field.type_() == crate::Array::static_type() {
1330                                let arr = field.get::<crate::Array>().unwrap();
1331                                debug.field(id, &arr);
1332                            } else if field.type_() == crate::List::static_type() {
1333                                let list = field.get::<crate::List>().unwrap();
1334                                debug.field(id, &list);
1335                            } else {
1336                                debug.field(id, &field);
1337                            }
1338                        }
1339
1340                        debug.finish()
1341                    }
1342                }
1343
1344                debug.field(&WithFeatures {
1345                    structure,
1346                    features,
1347                });
1348            }
1349
1350            debug.finish()
1351        }
1352    }
1353}
1354
1355impl fmt::Display for CapsRef {
1356    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1357        let s = unsafe { glib::GString::from_glib_full(ffi::gst_caps_to_string(self.as_ptr())) };
1358        f.write_str(&s)
1359    }
1360}
1361
1362impl PartialEq for CapsRef {
1363    #[doc(alias = "gst_caps_is_equal")]
1364    fn eq(&self, other: &CapsRef) -> bool {
1365        unsafe { from_glib(ffi::gst_caps_is_equal(self.as_ptr(), other.as_ptr())) }
1366    }
1367}
1368
1369impl Eq for CapsRef {}
1370
1371#[cfg(feature = "v1_28")]
1372impl std::hash::Hash for CapsRef {
1373    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1374        if self.is_any() {
1375            "ANY".hash(state);
1376        } else if self.is_empty() {
1377            "EMPTY".hash(state);
1378        } else {
1379            // do no sort as structure order matters
1380            for (s, feature) in self.iter_with_features() {
1381                s.hash(state);
1382                feature.hash(state);
1383            }
1384        }
1385    }
1386}
1387
1388#[cfg(feature = "v1_28")]
1389impl std::hash::Hash for Caps {
1390    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1391        self.as_ref().hash(state);
1392    }
1393}
1394
1395pub enum NoFeature {}
1396pub enum HasFeatures {}
1397
1398#[must_use = "The builder must be built to be used"]
1399pub struct Builder<T> {
1400    s: crate::Structure,
1401    features: Option<CapsFeatures>,
1402    phantom: PhantomData<T>,
1403}
1404
1405impl<T> fmt::Debug for Builder<T> {
1406    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1407        f.debug_struct("Builder")
1408            .field("s", &self.s)
1409            .field("features", &self.features)
1410            .field("phantom", &self.phantom)
1411            .finish()
1412    }
1413}
1414
1415impl Builder<NoFeature> {
1416    fn new(name: impl IntoGStr) -> Builder<NoFeature> {
1417        skip_assert_initialized!();
1418        Builder {
1419            s: crate::Structure::new_empty(name),
1420            features: None,
1421            phantom: PhantomData,
1422        }
1423    }
1424
1425    fn from_static(name: impl AsRef<GStr> + 'static) -> Builder<NoFeature> {
1426        skip_assert_initialized!();
1427        Builder {
1428            s: crate::Structure::new_empty_from_static(name),
1429            features: None,
1430            phantom: PhantomData,
1431        }
1432    }
1433
1434    fn from_id(name: impl AsRef<IdStr>) -> Builder<NoFeature> {
1435        skip_assert_initialized!();
1436        Builder {
1437            s: crate::Structure::new_empty_from_id(name),
1438            features: None,
1439            phantom: PhantomData,
1440        }
1441    }
1442
1443    pub fn features<S: IntoGStr>(
1444        self,
1445        features: impl IntoIterator<Item = S>,
1446    ) -> Builder<HasFeatures> {
1447        Builder {
1448            s: self.s,
1449            features: Some(CapsFeatures::new(features)),
1450            phantom: PhantomData,
1451        }
1452    }
1453
1454    pub fn features_from_statics<S: AsRef<GStr> + 'static>(
1455        self,
1456        features: impl IntoIterator<Item = S>,
1457    ) -> Builder<HasFeatures> {
1458        Builder {
1459            s: self.s,
1460            features: Some(CapsFeatures::new_from_static(features)),
1461            phantom: PhantomData,
1462        }
1463    }
1464
1465    pub fn features_from_ids<S: AsRef<IdStr>>(
1466        self,
1467        features: impl IntoIterator<Item = S>,
1468    ) -> Builder<HasFeatures> {
1469        Builder {
1470            s: self.s,
1471            features: Some(CapsFeatures::new_from_id(features)),
1472            phantom: PhantomData,
1473        }
1474    }
1475
1476    pub fn any_features(self) -> Builder<HasFeatures> {
1477        Builder {
1478            s: self.s,
1479            features: Some(CapsFeatures::new_any()),
1480            phantom: PhantomData,
1481        }
1482    }
1483}
1484
1485impl<T> Builder<T> {
1486    // rustdoc-stripper-ignore-next
1487    /// Sets field `name` to the given value `value`.
1488    ///
1489    /// Overrides any default or previously defined value for `name`.
1490    #[inline]
1491    pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self {
1492        self.s.set(name, value);
1493        self
1494    }
1495
1496    // rustdoc-stripper-ignore-next
1497    /// Sets field `name` to the given value `value`.
1498    ///
1499    /// Overrides any default or previously defined value for `name`.
1500    #[inline]
1501    pub fn field_with_static(
1502        mut self,
1503        name: impl AsRef<glib::GStr> + 'static,
1504        value: impl Into<glib::Value> + Send,
1505    ) -> Self {
1506        self.s.set_with_static(name, value);
1507        self
1508    }
1509
1510    // rustdoc-stripper-ignore-next
1511    /// Sets field `name` to the given value `value`.
1512    ///
1513    /// Overrides any default or previously defined value for `name`.
1514    #[inline]
1515    pub fn field_with_id(
1516        mut self,
1517        name: impl AsRef<IdStr>,
1518        value: impl Into<glib::Value> + Send,
1519    ) -> Self {
1520        self.s.set_with_id(name, value);
1521        self
1522    }
1523
1524    impl_builder_gvalue_extra_setters!(field);
1525
1526    #[must_use = "Building the caps without using them has no effect"]
1527    pub fn build(self) -> Caps {
1528        let mut caps = Caps::new_empty();
1529
1530        caps.get_mut()
1531            .unwrap()
1532            .append_structure_full(self.s, self.features);
1533        caps
1534    }
1535
1536    pub fn structure(&self) -> &crate::Structure {
1537        &self.s
1538    }
1539}
1540
1541pub enum AnyFeatures {}
1542pub enum SomeFeatures {}
1543
1544#[must_use = "The builder must be built to be used"]
1545pub struct BuilderFull<T> {
1546    caps: crate::Caps,
1547    features: Option<CapsFeatures>,
1548    phantom: PhantomData<T>,
1549}
1550
1551impl<T> fmt::Debug for BuilderFull<T> {
1552    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1553        f.debug_struct("Builder")
1554            .field("caps", &self.caps)
1555            .field("features", &self.features)
1556            .field("phantom", &self.phantom)
1557            .finish()
1558    }
1559}
1560
1561impl BuilderFull<SomeFeatures> {
1562    fn new() -> Self {
1563        BuilderFull {
1564            caps: Caps::new_empty(),
1565            features: None,
1566            phantom: PhantomData,
1567        }
1568    }
1569
1570    fn with_features(features: CapsFeatures) -> Self {
1571        skip_assert_initialized!();
1572        BuilderFull {
1573            caps: Caps::new_empty(),
1574            features: Some(features),
1575            phantom: PhantomData,
1576        }
1577    }
1578
1579    pub fn structure_with_features(self, structure: Structure, features: CapsFeatures) -> Self {
1580        self.append_structure(structure, Some(features))
1581    }
1582
1583    pub fn structure_with_features_if_some(
1584        self,
1585        structure: Option<Structure>,
1586        features: CapsFeatures,
1587    ) -> Self {
1588        if let Some(structure) = structure {
1589            self.structure_with_features(structure, features)
1590        } else {
1591            self
1592        }
1593    }
1594
1595    pub fn structure_with_any_features(self, structure: Structure) -> Self {
1596        self.append_structure(structure, Some(CapsFeatures::new_any()))
1597    }
1598
1599    pub fn structure_with_any_features_if_some(self, structure: Option<Structure>) -> Self {
1600        if let Some(structure) = structure {
1601            self.structure_with_any_features(structure)
1602        } else {
1603            self
1604        }
1605    }
1606}
1607
1608impl BuilderFull<AnyFeatures> {
1609    fn with_any_features() -> Self {
1610        BuilderFull {
1611            caps: Caps::new_empty(),
1612            features: Some(CapsFeatures::new_any()),
1613            phantom: PhantomData,
1614        }
1615    }
1616}
1617
1618impl<T> BuilderFull<T> {
1619    fn append_structure(mut self, structure: Structure, features: Option<CapsFeatures>) -> Self {
1620        let features = {
1621            match self.features {
1622                None => features,
1623                Some(ref result) => {
1624                    let mut result = result.clone();
1625                    match features {
1626                        None => Some(result),
1627                        Some(features) => {
1628                            features.iter().for_each(|feat| result.add(feat));
1629                            Some(result)
1630                        }
1631                    }
1632                }
1633            }
1634        };
1635
1636        self.caps
1637            .get_mut()
1638            .unwrap()
1639            .append_structure_full(structure, features);
1640        self
1641    }
1642
1643    pub fn structure(self, structure: Structure) -> Self {
1644        self.append_structure(structure, None)
1645    }
1646
1647    pub fn structure_if_some(self, structure: Option<Structure>) -> Self {
1648        if let Some(structure) = structure {
1649            self.structure(structure)
1650        } else {
1651            self
1652        }
1653    }
1654
1655    #[must_use = "Building the caps without using them has no effect"]
1656    pub fn build(self) -> Caps {
1657        self.caps
1658    }
1659}
1660
1661#[cfg(test)]
1662mod tests {
1663    use super::*;
1664    use crate::{Array, Fraction};
1665    use glib::gstr;
1666
1667    #[test]
1668    fn test_builder() {
1669        crate::init().unwrap();
1670
1671        let mut caps = Caps::builder("foo/bar")
1672            .field("int", 12)
1673            .field_with_static(gstr!("bool"), true)
1674            .field_with_id(idstr!("string"), "bla")
1675            .field("fraction", Fraction::new(1, 2))
1676            .field_with_id(idstr!("array"), Array::new([1, 2]))
1677            .build();
1678        assert_eq!(
1679            caps.to_string(),
1680            "foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >"
1681        );
1682
1683        assert!(
1684            caps.features(0)
1685                .unwrap()
1686                .is_equal(crate::CAPS_FEATURES_MEMORY_SYSTEM_MEMORY.as_ref())
1687        );
1688
1689        {
1690            let caps = caps.get_mut().unwrap();
1691            caps.set_features(0, Some(CapsFeatures::new(["foo:bla"])));
1692        }
1693        assert!(
1694            caps.features(0)
1695                .unwrap()
1696                .is_equal(CapsFeatures::new(["foo:bla"]).as_ref())
1697        );
1698
1699        let caps = Caps::builder("foo/bar")
1700            .field("int", 12)
1701            .any_features()
1702            .build();
1703        assert_eq!(caps.to_string(), "foo/bar(ANY), int=(int)12");
1704
1705        let caps = Caps::builder("foo/bar")
1706            .field("int", 12)
1707            .features(["foo:bla", "foo:baz"])
1708            .build();
1709        assert_eq!(caps.to_string(), "foo/bar(foo:bla, foo:baz), int=(int)12");
1710
1711        let caps = Caps::builder("foo/bar")
1712            .field_if_some("int0", Option::<i32>::None)
1713            .field_if_some("int1", Some(12))
1714            .field_with_static_if_some(gstr!("string0"), Option::<String>::None)
1715            .field_with_id_if_some(idstr!("string1"), Some("bla"))
1716            .build();
1717        assert_eq!(
1718            caps.to_string(),
1719            "foo/bar, int1=(int)12, string1=(string)bla"
1720        );
1721    }
1722
1723    #[test]
1724    fn test_display() {
1725        crate::init().unwrap();
1726
1727        let caps = Caps::builder("foo/bar").build();
1728        let _ = format!("{caps}");
1729    }
1730
1731    #[test]
1732    fn test_builder_full() {
1733        crate::init().unwrap();
1734
1735        let caps = Caps::builder_full()
1736            .structure(Structure::builder("audio/x-raw").build())
1737            .structure(Structure::builder("video/x-raw").build())
1738            .build();
1739        assert_eq!(caps.to_string(), "audio/x-raw; video/x-raw");
1740
1741        let caps = Caps::builder_full()
1742            .structure(
1743                Structure::builder("audio/x-raw")
1744                    .field("format", "S16LE")
1745                    .build(),
1746            )
1747            .structure(Structure::builder("video/x-raw").build())
1748            .build();
1749        assert_eq!(
1750            caps.to_string(),
1751            "audio/x-raw, format=(string)S16LE; video/x-raw"
1752        );
1753
1754        let caps = Caps::builder_full()
1755            .structure_with_any_features(Structure::builder("audio/x-raw").build())
1756            .structure_with_features(
1757                Structure::builder("video/x-raw").build(),
1758                CapsFeatures::new(["foo:bla", "foo:baz"]),
1759            )
1760            .build();
1761        assert_eq!(
1762            caps.to_string(),
1763            "audio/x-raw(ANY); video/x-raw(foo:bla, foo:baz)"
1764        );
1765
1766        let caps = Caps::builder_full()
1767            .structure_if_some(Option::<Structure>::None)
1768            .build();
1769        assert!(caps.is_empty());
1770
1771        let caps = Caps::builder_full()
1772            .structure_if_some(Some(Structure::builder("audio/x-raw").build()))
1773            .build();
1774        assert_eq!(caps.to_string(), "audio/x-raw");
1775
1776        let caps = Caps::builder_full()
1777            .structure_with_any_features_if_some(Some(Structure::builder("audio/x-raw").build()))
1778            .structure_with_features_if_some(
1779                Some(Structure::builder("video/x-raw").build()),
1780                CapsFeatures::new_from_id([idstr!("foo:bla"), idstr!("foo:baz")]),
1781            )
1782            .build();
1783        assert_eq!(
1784            caps.to_string(),
1785            "audio/x-raw(ANY); video/x-raw(foo:bla, foo:baz)"
1786        );
1787
1788        let caps = Caps::builder_full()
1789            .structure_with_any_features_if_some(Option::<Structure>::None)
1790            .structure_with_features_if_some(
1791                Option::<Structure>::None,
1792                CapsFeatures::new(["foo:bla", "foo:baz"]),
1793            )
1794            .build();
1795        assert!(caps.is_empty());
1796    }
1797
1798    #[test]
1799    fn test_builder_full_with_features() {
1800        crate::init().unwrap();
1801
1802        let caps = Caps::builder_full_with_features(CapsFeatures::new(["foo:bla"]))
1803            .structure(Structure::builder("audio/x-raw").build())
1804            .structure_with_features(
1805                Structure::builder("video/x-raw").build(),
1806                CapsFeatures::new(["foo:baz"]),
1807            )
1808            .build();
1809        assert_eq!(
1810            caps.to_string(),
1811            "audio/x-raw(foo:bla); video/x-raw(foo:bla, foo:baz)"
1812        );
1813    }
1814
1815    #[test]
1816    fn test_builder_full_with_any_features() {
1817        crate::init().unwrap();
1818
1819        let caps = Caps::builder_full_with_any_features()
1820            .structure(Structure::builder("audio/x-raw").build())
1821            .structure(Structure::builder("video/x-raw").build())
1822            .build();
1823        assert_eq!(caps.to_string(), "audio/x-raw(ANY); video/x-raw(ANY)");
1824
1825        let caps = Caps::builder_full_with_any_features()
1826            .structure(Structure::builder("audio/x-raw").build())
1827            .build();
1828        assert_eq!(caps.to_string(), "audio/x-raw(ANY)");
1829    }
1830
1831    #[test]
1832    fn test_new_from_iter() {
1833        crate::init().unwrap();
1834
1835        let caps = Caps::builder_full_with_any_features()
1836            .structure(Structure::builder("audio/x-raw").build())
1837            .structure(Structure::builder("video/x-raw").build())
1838            .build();
1839
1840        let audio = caps
1841            .iter()
1842            .filter(|s| s.name() == "audio/x-raw")
1843            .map(|s| s.to_owned())
1844            .collect::<Caps>();
1845        assert_eq!(audio.to_string(), "audio/x-raw");
1846
1847        let audio = caps
1848            .iter_with_features()
1849            .filter(|(s, _)| s.name() == "audio/x-raw")
1850            .map(|(s, c)| (s.to_owned(), c.to_owned()))
1851            .collect::<Caps>();
1852        assert_eq!(audio.to_string(), "audio/x-raw(ANY)");
1853    }
1854
1855    #[test]
1856    fn test_debug() {
1857        crate::init().unwrap();
1858
1859        let caps = Caps::new_any();
1860        assert_eq!(format!("{caps:?}"), "Caps(\"ANY\")");
1861
1862        let caps = Caps::new_empty();
1863        assert_eq!(format!("{caps:?}"), "Caps(\"EMPTY\")");
1864
1865        let caps = Caps::builder_full_with_any_features()
1866            .structure(Structure::builder("audio/x-raw").build())
1867            .build();
1868        assert_eq!(format!("{caps:?}"), "Caps(audio/x-raw(ANY))");
1869
1870        let caps = Caps::builder_full_with_features(CapsFeatures::new(["foo:bla"]))
1871            .structure(
1872                Structure::builder("audio/x-raw")
1873                    .field(
1874                        "struct",
1875                        Structure::builder("nested").field("badger", true).build(),
1876                    )
1877                    .build(),
1878            )
1879            .structure(
1880                Structure::builder("video/x-raw")
1881                    .field("width", 800u32)
1882                    .build(),
1883            )
1884            .build();
1885
1886        assert_eq!(
1887            format!("{caps:?}"),
1888            "Caps(audio/x-raw(foo:bla) { struct: Structure(nested { badger: (gboolean) TRUE }) }, video/x-raw(foo:bla) { width: (guint) 800 })"
1889        );
1890
1891        let caps = Caps::builder_full()
1892            .structure(
1893                Structure::builder("video/x-raw")
1894                    .field("array", crate::Array::new(["a", "b", "c"]))
1895                    .field("list", crate::List::new(["d", "e", "f"]))
1896                    .build(),
1897            )
1898            .build();
1899
1900        assert_eq!(
1901            format!("{caps:?}"),
1902            "Caps(video/x-raw(memory:SystemMemory) { array: Array([(gchararray) \"a\", (gchararray) \"b\", (gchararray) \"c\"]), list: List([(gchararray) \"d\", (gchararray) \"e\", (gchararray) \"f\"]) })"
1903        );
1904    }
1905
1906    #[cfg(feature = "v1_28")]
1907    #[test]
1908    fn test_hash() {
1909        crate::init().unwrap();
1910
1911        use std::hash::BuildHasher;
1912        let bh = std::hash::RandomState::new();
1913
1914        let caps = Caps::builder("video/x-raw").build();
1915        assert_eq!(bh.hash_one(&caps), bh.hash_one(&caps));
1916
1917        let caps_any = Caps::new_any();
1918        let caps_empty = Caps::new_empty();
1919        assert_eq!(bh.hash_one(&caps_any), bh.hash_one(&caps_any));
1920        assert_eq!(bh.hash_one(&caps_empty), bh.hash_one(&caps_empty));
1921        assert_ne!(bh.hash_one(&caps_any), bh.hash_one(&caps_empty));
1922
1923        // Same caps but fields in a different order
1924        let caps_a = Caps::builder("video/x-raw")
1925            .field("width", 1920u32)
1926            .field("height", 1080u32)
1927            .build();
1928        let caps_b = Caps::builder("video/x-raw")
1929            .field("height", 1080u32)
1930            .field("width", 1920u32)
1931            .build();
1932        assert_eq!(bh.hash_one(&caps_a), bh.hash_one(&caps_a));
1933        assert_eq!(bh.hash_one(&caps_b), bh.hash_one(&caps_b));
1934        assert_eq!(bh.hash_one(&caps_a), bh.hash_one(&caps_b));
1935
1936        // Same fields but different feature
1937        let caps_a = Caps::builder("video/x-raw")
1938            .features(["memory:DMABuf"])
1939            .field("width", 1920u32)
1940            .field("height", 1080u32)
1941            .build();
1942        let caps_b = Caps::builder("video/x-raw")
1943            .features(["memory:GLMemory"])
1944            .field("height", 1080u32)
1945            .field("width", 1920u32)
1946            .build();
1947        assert_eq!(bh.hash_one(&caps_a), bh.hash_one(&caps_a));
1948        assert_eq!(bh.hash_one(&caps_b), bh.hash_one(&caps_b));
1949        assert_ne!(bh.hash_one(&caps_a), bh.hash_one(&caps_b));
1950
1951        // Caps have the same structures but in different order, so they are actually different
1952        let caps_a = Caps::builder_full()
1953            .structure(Structure::builder("audio/x-raw").build())
1954            .structure(Structure::builder("video/x-raw").build())
1955            .build();
1956        let caps_b = Caps::builder_full()
1957            .structure(Structure::builder("video/x-raw").build())
1958            .structure(Structure::builder("audio/x-raw").build())
1959            .build();
1960        assert_eq!(bh.hash_one(&caps_a), bh.hash_one(&caps_a));
1961        assert_eq!(bh.hash_one(&caps_b), bh.hash_one(&caps_b));
1962        assert_ne!(bh.hash_one(&caps_a), bh.hash_one(&caps_b));
1963    }
1964}