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