gstreamer/
caps.rs

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