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