1use 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 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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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 #[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 #[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 #[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 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 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 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}