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    prelude::*,
8    translate::*,
9    value::{SendValue, ToSendValue},
10    GStr,
11};
12
13use crate::{caps_features::*, ffi, structure::*, CapsIntersectMode, IdStr};
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 `gst_caps_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 `gst_caps_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 `gst_caps_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 `gst_caps_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                let func = &mut *(user_data as *mut F);
1102                let res = func(
1103                    CapsFeaturesRef::from_glib_borrow(features),
1104                    StructureRef::from_glib_borrow(s),
1105                );
1106
1107                matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1108            }
1109            let func = &mut func as *mut F;
1110            from_glib(ffi::gst_caps_foreach(
1111                self.as_ptr(),
1112                Some(trampoline::<F>),
1113                func as glib::ffi::gpointer,
1114            ))
1115        }
1116    }
1117
1118    #[doc(alias = "gst_caps_map_in_place")]
1119    pub fn map_in_place<
1120        F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> std::ops::ControlFlow<()>,
1121    >(
1122        &mut self,
1123        mut func: F,
1124    ) {
1125        unsafe {
1126            unsafe extern "C" fn trampoline<
1127                F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> std::ops::ControlFlow<()>,
1128            >(
1129                features: *mut ffi::GstCapsFeatures,
1130                s: *mut ffi::GstStructure,
1131                user_data: glib::ffi::gpointer,
1132            ) -> glib::ffi::gboolean {
1133                let func = &mut *(user_data as *mut F);
1134                let res = func(
1135                    CapsFeaturesRef::from_glib_borrow_mut(features),
1136                    StructureRef::from_glib_borrow_mut(s),
1137                );
1138
1139                matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1140            }
1141            let func = &mut func as *mut F;
1142            let _ = ffi::gst_caps_map_in_place(
1143                self.as_mut_ptr(),
1144                Some(trampoline::<F>),
1145                func as glib::ffi::gpointer,
1146            );
1147        }
1148    }
1149
1150    #[doc(alias = "gst_caps_filter_and_map_in_place")]
1151    pub fn filter_map_in_place<
1152        F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> CapsFilterMapAction,
1153    >(
1154        &mut self,
1155        mut func: F,
1156    ) {
1157        unsafe {
1158            unsafe extern "C" fn trampoline<
1159                F: FnMut(&mut CapsFeaturesRef, &mut StructureRef) -> CapsFilterMapAction,
1160            >(
1161                features: *mut ffi::GstCapsFeatures,
1162                s: *mut ffi::GstStructure,
1163                user_data: glib::ffi::gpointer,
1164            ) -> glib::ffi::gboolean {
1165                let func = &mut *(user_data as *mut F);
1166
1167                let res = func(
1168                    CapsFeaturesRef::from_glib_borrow_mut(features),
1169                    StructureRef::from_glib_borrow_mut(s),
1170                );
1171
1172                match res {
1173                    CapsFilterMapAction::Keep => glib::ffi::GTRUE,
1174                    CapsFilterMapAction::Remove => glib::ffi::GFALSE,
1175                }
1176            }
1177
1178            let func = &mut func as *mut F;
1179            ffi::gst_caps_filter_and_map_in_place(
1180                self.as_mut_ptr(),
1181                Some(trampoline::<F>),
1182                func as glib::ffi::gpointer,
1183            );
1184        }
1185    }
1186}
1187
1188#[derive(Debug)]
1189pub enum CapsFilterMapAction {
1190    Keep,
1191    Remove,
1192}
1193
1194macro_rules! define_iter(
1195    ($name:ident, $typ:ty, $styp:ty, $get_item:expr) => {
1196        crate::utils::define_fixed_size_iter!(
1197            $name, $typ, $styp,
1198            |collection: &CapsRef| collection.size(),
1199            $get_item
1200        );
1201    }
1202);
1203
1204define_iter!(
1205    Iter,
1206    &'a CapsRef,
1207    &'a StructureRef,
1208    |caps: &CapsRef, idx| unsafe {
1209        let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32);
1210        StructureRef::from_glib_borrow(ptr as *const ffi::GstStructure)
1211    }
1212);
1213define_iter!(
1214    IterMut,
1215    &'a mut CapsRef,
1216    &'a mut StructureRef,
1217    |caps: &mut CapsRef, idx| unsafe {
1218        let ptr = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32);
1219        StructureRef::from_glib_borrow_mut(ptr)
1220    }
1221);
1222define_iter!(
1223    IterFeatures,
1224    &'a CapsRef,
1225    (&'a StructureRef, &'a CapsFeaturesRef),
1226    |caps: &CapsRef, idx| unsafe {
1227        let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32);
1228        let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx as u32);
1229        (
1230            StructureRef::from_glib_borrow(ptr1),
1231            CapsFeaturesRef::from_glib_borrow(ptr2),
1232        )
1233    }
1234);
1235define_iter!(
1236    IterFeaturesMut,
1237    &'a mut CapsRef,
1238    (&'a mut StructureRef, &'a mut CapsFeaturesRef),
1239    |caps: &mut CapsRef, idx| unsafe {
1240        let ptr1 = ffi::gst_caps_get_structure(caps.as_ptr(), idx as u32);
1241        let ptr2 = ffi::gst_caps_get_features(caps.as_ptr(), idx as u32);
1242        (
1243            StructureRef::from_glib_borrow_mut(ptr1),
1244            CapsFeaturesRef::from_glib_borrow_mut(ptr2),
1245        )
1246    }
1247);
1248
1249impl<'a> IntoIterator for &'a CapsRef {
1250    type IntoIter = IterFeatures<'a>;
1251    type Item = (&'a StructureRef, &'a CapsFeaturesRef);
1252
1253    fn into_iter(self) -> Self::IntoIter {
1254        self.iter_with_features()
1255    }
1256}
1257
1258impl<'a> IntoIterator for &'a mut CapsRef {
1259    type IntoIter = IterFeaturesMut<'a>;
1260    type Item = (&'a mut StructureRef, &'a mut CapsFeaturesRef);
1261
1262    fn into_iter(self) -> Self::IntoIter {
1263        self.iter_with_features_mut()
1264    }
1265}
1266
1267impl fmt::Debug for Caps {
1268    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1269        <CapsRef as fmt::Debug>::fmt(self, f)
1270    }
1271}
1272
1273impl fmt::Display for Caps {
1274    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1275        <CapsRef as fmt::Display>::fmt(self, f)
1276    }
1277}
1278
1279impl PartialEq for Caps {
1280    fn eq(&self, other: &Caps) -> bool {
1281        CapsRef::eq(self, other)
1282    }
1283}
1284
1285impl Eq for Caps {}
1286
1287impl PartialEq<CapsRef> for Caps {
1288    fn eq(&self, other: &CapsRef) -> bool {
1289        CapsRef::eq(self, other)
1290    }
1291}
1292
1293impl PartialEq<Caps> for CapsRef {
1294    fn eq(&self, other: &Caps) -> bool {
1295        CapsRef::eq(other, self)
1296    }
1297}
1298
1299impl fmt::Debug for CapsRef {
1300    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1301        if self.is_any() {
1302            f.debug_tuple("Caps(\"ANY\")").finish()
1303        } else if self.is_empty() {
1304            f.debug_tuple("Caps(\"EMPTY\")").finish()
1305        } else {
1306            let mut debug = f.debug_tuple("Caps");
1307
1308            for (structure, features) in self.iter_with_features() {
1309                struct WithFeatures<'a> {
1310                    features: &'a CapsFeaturesRef,
1311                    structure: &'a StructureRef,
1312                }
1313
1314                impl fmt::Debug for WithFeatures<'_> {
1315                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1316                        let name = format!("{}({})", self.structure.name(), self.features);
1317                        let mut debug = f.debug_struct(&name);
1318
1319                        for (id, field) in self.structure.iter() {
1320                            if field.type_() == Structure::static_type() {
1321                                let s = field.get::<Structure>().unwrap();
1322                                debug.field(id, &s);
1323                            } else if field.type_() == crate::Array::static_type() {
1324                                let arr = field.get::<crate::Array>().unwrap();
1325                                debug.field(id, &arr);
1326                            } else if field.type_() == crate::List::static_type() {
1327                                let list = field.get::<crate::List>().unwrap();
1328                                debug.field(id, &list);
1329                            } else {
1330                                debug.field(id, &field);
1331                            }
1332                        }
1333
1334                        debug.finish()
1335                    }
1336                }
1337
1338                debug.field(&WithFeatures {
1339                    structure,
1340                    features,
1341                });
1342            }
1343
1344            debug.finish()
1345        }
1346    }
1347}
1348
1349impl fmt::Display for CapsRef {
1350    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1351        let s = unsafe { glib::GString::from_glib_full(ffi::gst_caps_to_string(self.as_ptr())) };
1352        f.write_str(&s)
1353    }
1354}
1355
1356impl PartialEq for CapsRef {
1357    #[doc(alias = "gst_caps_is_equal")]
1358    fn eq(&self, other: &CapsRef) -> bool {
1359        unsafe { from_glib(ffi::gst_caps_is_equal(self.as_ptr(), other.as_ptr())) }
1360    }
1361}
1362
1363impl Eq for CapsRef {}
1364
1365pub enum NoFeature {}
1366pub enum HasFeatures {}
1367
1368#[must_use = "The builder must be built to be used"]
1369pub struct Builder<T> {
1370    s: crate::Structure,
1371    features: Option<CapsFeatures>,
1372    phantom: PhantomData<T>,
1373}
1374
1375impl<T> fmt::Debug for Builder<T> {
1376    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1377        f.debug_struct("Builder")
1378            .field("s", &self.s)
1379            .field("features", &self.features)
1380            .field("phantom", &self.phantom)
1381            .finish()
1382    }
1383}
1384
1385impl Builder<NoFeature> {
1386    fn new(name: impl IntoGStr) -> Builder<NoFeature> {
1387        skip_assert_initialized!();
1388        Builder {
1389            s: crate::Structure::new_empty(name),
1390            features: None,
1391            phantom: PhantomData,
1392        }
1393    }
1394
1395    fn from_static(name: impl AsRef<GStr> + 'static) -> Builder<NoFeature> {
1396        skip_assert_initialized!();
1397        Builder {
1398            s: crate::Structure::new_empty_from_static(name),
1399            features: None,
1400            phantom: PhantomData,
1401        }
1402    }
1403
1404    fn from_id(name: impl AsRef<IdStr>) -> Builder<NoFeature> {
1405        skip_assert_initialized!();
1406        Builder {
1407            s: crate::Structure::new_empty_from_id(name),
1408            features: None,
1409            phantom: PhantomData,
1410        }
1411    }
1412
1413    pub fn features<S: IntoGStr>(
1414        self,
1415        features: impl IntoIterator<Item = S>,
1416    ) -> Builder<HasFeatures> {
1417        Builder {
1418            s: self.s,
1419            features: Some(CapsFeatures::new(features)),
1420            phantom: PhantomData,
1421        }
1422    }
1423
1424    pub fn features_from_statics<S: AsRef<GStr> + 'static>(
1425        self,
1426        features: impl IntoIterator<Item = S>,
1427    ) -> Builder<HasFeatures> {
1428        Builder {
1429            s: self.s,
1430            features: Some(CapsFeatures::new_from_static(features)),
1431            phantom: PhantomData,
1432        }
1433    }
1434
1435    pub fn features_from_ids<S: AsRef<IdStr>>(
1436        self,
1437        features: impl IntoIterator<Item = S>,
1438    ) -> Builder<HasFeatures> {
1439        Builder {
1440            s: self.s,
1441            features: Some(CapsFeatures::new_from_id(features)),
1442            phantom: PhantomData,
1443        }
1444    }
1445
1446    pub fn any_features(self) -> Builder<HasFeatures> {
1447        Builder {
1448            s: self.s,
1449            features: Some(CapsFeatures::new_any()),
1450            phantom: PhantomData,
1451        }
1452    }
1453}
1454
1455impl<T> Builder<T> {
1456    // rustdoc-stripper-ignore-next
1457    /// Sets field `name` to the given value `value`.
1458    ///
1459    /// Overrides any default or previously defined value for `name`.
1460    #[inline]
1461    pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self {
1462        self.s.set(name, value);
1463        self
1464    }
1465
1466    // rustdoc-stripper-ignore-next
1467    /// Sets field `name` to the given value `value`.
1468    ///
1469    /// Overrides any default or previously defined value for `name`.
1470    #[inline]
1471    pub fn field_with_static(
1472        mut self,
1473        name: impl AsRef<glib::GStr> + 'static,
1474        value: impl Into<glib::Value> + Send,
1475    ) -> Self {
1476        self.s.set_with_static(name, value);
1477        self
1478    }
1479
1480    // rustdoc-stripper-ignore-next
1481    /// Sets field `name` to the given value `value`.
1482    ///
1483    /// Overrides any default or previously defined value for `name`.
1484    #[inline]
1485    pub fn field_with_id(
1486        mut self,
1487        name: impl AsRef<IdStr>,
1488        value: impl Into<glib::Value> + Send,
1489    ) -> Self {
1490        self.s.set_with_id(name, value);
1491        self
1492    }
1493
1494    impl_builder_gvalue_extra_setters!(field);
1495
1496    #[must_use = "Building the caps without using them has no effect"]
1497    pub fn build(self) -> Caps {
1498        let mut caps = Caps::new_empty();
1499
1500        caps.get_mut()
1501            .unwrap()
1502            .append_structure_full(self.s, self.features);
1503        caps
1504    }
1505
1506    pub fn structure(&self) -> &crate::Structure {
1507        &self.s
1508    }
1509}
1510
1511pub enum AnyFeatures {}
1512pub enum SomeFeatures {}
1513
1514#[must_use = "The builder must be built to be used"]
1515pub struct BuilderFull<T> {
1516    caps: crate::Caps,
1517    features: Option<CapsFeatures>,
1518    phantom: PhantomData<T>,
1519}
1520
1521impl<T> fmt::Debug for BuilderFull<T> {
1522    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1523        f.debug_struct("Builder")
1524            .field("caps", &self.caps)
1525            .field("features", &self.features)
1526            .field("phantom", &self.phantom)
1527            .finish()
1528    }
1529}
1530
1531impl BuilderFull<SomeFeatures> {
1532    fn new() -> Self {
1533        BuilderFull {
1534            caps: Caps::new_empty(),
1535            features: None,
1536            phantom: PhantomData,
1537        }
1538    }
1539
1540    fn with_features(features: CapsFeatures) -> Self {
1541        skip_assert_initialized!();
1542        BuilderFull {
1543            caps: Caps::new_empty(),
1544            features: Some(features),
1545            phantom: PhantomData,
1546        }
1547    }
1548
1549    pub fn structure_with_features(self, structure: Structure, features: CapsFeatures) -> Self {
1550        self.append_structure(structure, Some(features))
1551    }
1552
1553    pub fn structure_with_features_if_some(
1554        self,
1555        structure: Option<Structure>,
1556        features: CapsFeatures,
1557    ) -> Self {
1558        if let Some(structure) = structure {
1559            self.structure_with_features(structure, features)
1560        } else {
1561            self
1562        }
1563    }
1564
1565    pub fn structure_with_any_features(self, structure: Structure) -> Self {
1566        self.append_structure(structure, Some(CapsFeatures::new_any()))
1567    }
1568
1569    pub fn structure_with_any_features_if_some(self, structure: Option<Structure>) -> Self {
1570        if let Some(structure) = structure {
1571            self.structure_with_any_features(structure)
1572        } else {
1573            self
1574        }
1575    }
1576}
1577
1578impl BuilderFull<AnyFeatures> {
1579    fn with_any_features() -> Self {
1580        BuilderFull {
1581            caps: Caps::new_empty(),
1582            features: Some(CapsFeatures::new_any()),
1583            phantom: PhantomData,
1584        }
1585    }
1586}
1587
1588impl<T> BuilderFull<T> {
1589    fn append_structure(mut self, structure: Structure, features: Option<CapsFeatures>) -> Self {
1590        let features = {
1591            match self.features {
1592                None => features,
1593                Some(ref result) => {
1594                    let mut result = result.clone();
1595                    match features {
1596                        None => Some(result),
1597                        Some(features) => {
1598                            features.iter().for_each(|feat| result.add(feat));
1599                            Some(result)
1600                        }
1601                    }
1602                }
1603            }
1604        };
1605
1606        self.caps
1607            .get_mut()
1608            .unwrap()
1609            .append_structure_full(structure, features);
1610        self
1611    }
1612
1613    pub fn structure(self, structure: Structure) -> Self {
1614        self.append_structure(structure, None)
1615    }
1616
1617    pub fn structure_if_some(self, structure: Option<Structure>) -> Self {
1618        if let Some(structure) = structure {
1619            self.structure(structure)
1620        } else {
1621            self
1622        }
1623    }
1624
1625    #[must_use = "Building the caps without using them has no effect"]
1626    pub fn build(self) -> Caps {
1627        self.caps
1628    }
1629}
1630
1631#[cfg(test)]
1632mod tests {
1633    use super::*;
1634    use crate::{Array, Fraction};
1635    use glib::gstr;
1636
1637    #[test]
1638    fn test_builder() {
1639        crate::init().unwrap();
1640
1641        let mut caps = Caps::builder("foo/bar")
1642            .field("int", 12)
1643            .field_with_static(gstr!("bool"), true)
1644            .field_with_id(idstr!("string"), "bla")
1645            .field("fraction", Fraction::new(1, 2))
1646            .field_with_id(idstr!("array"), Array::new([1, 2]))
1647            .build();
1648        assert_eq!(
1649            caps.to_string(),
1650            "foo/bar, int=(int)12, bool=(boolean)true, string=(string)bla, fraction=(fraction)1/2, array=(int)< 1, 2 >"
1651        );
1652
1653        assert!(caps
1654            .features(0)
1655            .unwrap()
1656            .is_equal(crate::CAPS_FEATURES_MEMORY_SYSTEM_MEMORY.as_ref()));
1657
1658        {
1659            let caps = caps.get_mut().unwrap();
1660            caps.set_features(0, Some(CapsFeatures::new(["foo:bla"])));
1661        }
1662        assert!(caps
1663            .features(0)
1664            .unwrap()
1665            .is_equal(CapsFeatures::new(["foo:bla"]).as_ref()));
1666
1667        let caps = Caps::builder("foo/bar")
1668            .field("int", 12)
1669            .any_features()
1670            .build();
1671        assert_eq!(caps.to_string(), "foo/bar(ANY), int=(int)12");
1672
1673        let caps = Caps::builder("foo/bar")
1674            .field("int", 12)
1675            .features(["foo:bla", "foo:baz"])
1676            .build();
1677        assert_eq!(caps.to_string(), "foo/bar(foo:bla, foo:baz), int=(int)12");
1678
1679        let caps = Caps::builder("foo/bar")
1680            .field_if_some("int0", Option::<i32>::None)
1681            .field_if_some("int1", Some(12))
1682            .field_with_static_if_some(gstr!("string0"), Option::<String>::None)
1683            .field_with_id_if_some(idstr!("string1"), Some("bla"))
1684            .build();
1685        assert_eq!(
1686            caps.to_string(),
1687            "foo/bar, int1=(int)12, string1=(string)bla"
1688        );
1689    }
1690
1691    #[test]
1692    fn test_display() {
1693        crate::init().unwrap();
1694
1695        let caps = Caps::builder("foo/bar").build();
1696        let _ = format!("{caps}");
1697    }
1698
1699    #[test]
1700    fn test_builder_full() {
1701        crate::init().unwrap();
1702
1703        let caps = Caps::builder_full()
1704            .structure(Structure::builder("audio/x-raw").build())
1705            .structure(Structure::builder("video/x-raw").build())
1706            .build();
1707        assert_eq!(caps.to_string(), "audio/x-raw; video/x-raw");
1708
1709        let caps = Caps::builder_full()
1710            .structure(
1711                Structure::builder("audio/x-raw")
1712                    .field("format", "S16LE")
1713                    .build(),
1714            )
1715            .structure(Structure::builder("video/x-raw").build())
1716            .build();
1717        assert_eq!(
1718            caps.to_string(),
1719            "audio/x-raw, format=(string)S16LE; video/x-raw"
1720        );
1721
1722        let caps = Caps::builder_full()
1723            .structure_with_any_features(Structure::builder("audio/x-raw").build())
1724            .structure_with_features(
1725                Structure::builder("video/x-raw").build(),
1726                CapsFeatures::new(["foo:bla", "foo:baz"]),
1727            )
1728            .build();
1729        assert_eq!(
1730            caps.to_string(),
1731            "audio/x-raw(ANY); video/x-raw(foo:bla, foo:baz)"
1732        );
1733
1734        let caps = Caps::builder_full()
1735            .structure_if_some(Option::<Structure>::None)
1736            .build();
1737        assert!(caps.is_empty());
1738
1739        let caps = Caps::builder_full()
1740            .structure_if_some(Some(Structure::builder("audio/x-raw").build()))
1741            .build();
1742        assert_eq!(caps.to_string(), "audio/x-raw");
1743
1744        let caps = Caps::builder_full()
1745            .structure_with_any_features_if_some(Some(Structure::builder("audio/x-raw").build()))
1746            .structure_with_features_if_some(
1747                Some(Structure::builder("video/x-raw").build()),
1748                CapsFeatures::new_from_id([idstr!("foo:bla"), idstr!("foo:baz")]),
1749            )
1750            .build();
1751        assert_eq!(
1752            caps.to_string(),
1753            "audio/x-raw(ANY); video/x-raw(foo:bla, foo:baz)"
1754        );
1755
1756        let caps = Caps::builder_full()
1757            .structure_with_any_features_if_some(Option::<Structure>::None)
1758            .structure_with_features_if_some(
1759                Option::<Structure>::None,
1760                CapsFeatures::new(["foo:bla", "foo:baz"]),
1761            )
1762            .build();
1763        assert!(caps.is_empty());
1764    }
1765
1766    #[test]
1767    fn test_builder_full_with_features() {
1768        crate::init().unwrap();
1769
1770        let caps = Caps::builder_full_with_features(CapsFeatures::new(["foo:bla"]))
1771            .structure(Structure::builder("audio/x-raw").build())
1772            .structure_with_features(
1773                Structure::builder("video/x-raw").build(),
1774                CapsFeatures::new(["foo:baz"]),
1775            )
1776            .build();
1777        assert_eq!(
1778            caps.to_string(),
1779            "audio/x-raw(foo:bla); video/x-raw(foo:bla, foo:baz)"
1780        );
1781    }
1782
1783    #[test]
1784    fn test_builder_full_with_any_features() {
1785        crate::init().unwrap();
1786
1787        let caps = Caps::builder_full_with_any_features()
1788            .structure(Structure::builder("audio/x-raw").build())
1789            .structure(Structure::builder("video/x-raw").build())
1790            .build();
1791        assert_eq!(caps.to_string(), "audio/x-raw(ANY); video/x-raw(ANY)");
1792
1793        let caps = Caps::builder_full_with_any_features()
1794            .structure(Structure::builder("audio/x-raw").build())
1795            .build();
1796        assert_eq!(caps.to_string(), "audio/x-raw(ANY)");
1797    }
1798
1799    #[test]
1800    fn test_new_from_iter() {
1801        crate::init().unwrap();
1802
1803        let caps = Caps::builder_full_with_any_features()
1804            .structure(Structure::builder("audio/x-raw").build())
1805            .structure(Structure::builder("video/x-raw").build())
1806            .build();
1807
1808        let audio = caps
1809            .iter()
1810            .filter(|s| s.name() == "audio/x-raw")
1811            .map(|s| s.to_owned())
1812            .collect::<Caps>();
1813        assert_eq!(audio.to_string(), "audio/x-raw");
1814
1815        let audio = caps
1816            .iter_with_features()
1817            .filter(|(s, _)| s.name() == "audio/x-raw")
1818            .map(|(s, c)| (s.to_owned(), c.to_owned()))
1819            .collect::<Caps>();
1820        assert_eq!(audio.to_string(), "audio/x-raw(ANY)");
1821    }
1822
1823    #[test]
1824    fn test_debug() {
1825        crate::init().unwrap();
1826
1827        let caps = Caps::new_any();
1828        assert_eq!(format!("{caps:?}"), "Caps(\"ANY\")");
1829
1830        let caps = Caps::new_empty();
1831        assert_eq!(format!("{caps:?}"), "Caps(\"EMPTY\")");
1832
1833        let caps = Caps::builder_full_with_any_features()
1834            .structure(Structure::builder("audio/x-raw").build())
1835            .build();
1836        assert_eq!(format!("{caps:?}"), "Caps(audio/x-raw(ANY))");
1837
1838        let caps = Caps::builder_full_with_features(CapsFeatures::new(["foo:bla"]))
1839            .structure(
1840                Structure::builder("audio/x-raw")
1841                    .field(
1842                        "struct",
1843                        Structure::builder("nested").field("badger", true).build(),
1844                    )
1845                    .build(),
1846            )
1847            .structure(
1848                Structure::builder("video/x-raw")
1849                    .field("width", 800u32)
1850                    .build(),
1851            )
1852            .build();
1853
1854        assert_eq!(format!("{caps:?}"), "Caps(audio/x-raw(foo:bla) { struct: Structure(nested { badger: (gboolean) TRUE }) }, video/x-raw(foo:bla) { width: (guint) 800 })");
1855
1856        let caps = Caps::builder_full()
1857            .structure(
1858                Structure::builder("video/x-raw")
1859                    .field("array", crate::Array::new(["a", "b", "c"]))
1860                    .field("list", crate::List::new(["d", "e", "f"]))
1861                    .build(),
1862            )
1863            .build();
1864
1865        assert_eq!(format!("{caps:?}"), "Caps(video/x-raw(memory:SystemMemory) { array: Array([(gchararray) \"a\", (gchararray) \"b\", (gchararray) \"c\"]), list: List([(gchararray) \"d\", (gchararray) \"e\", (gchararray) \"f\"]) })");
1866    }
1867}