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