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