1use std::{
4 borrow::{Borrow, BorrowMut, ToOwned},
5 fmt,
6 marker::PhantomData,
7 mem,
8 ops::{Deref, DerefMut},
9 ptr, str,
10};
11
12use cfg_if::cfg_if;
13use glib::{
14 GStr, IntoGStr,
15 prelude::*,
16 translate::*,
17 value::{FromValue, SendValue, Value},
18};
19
20use crate::{Fraction, IdStr, ffi};
21
22#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
23pub enum GetError<E: std::error::Error> {
24 #[error("GetError: Structure field with name {name} not found")]
25 FieldNotFound { name: IdStr },
26 #[error("GetError: Structure field with name {name} not retrieved")]
27 ValueGetError {
28 name: IdStr,
29 #[source]
30 error: E,
31 },
32}
33
34impl<E: std::error::Error> GetError<E> {
35 #[inline]
36 fn new_field_not_found(name: impl AsRef<IdStr>) -> Self {
37 skip_assert_initialized!();
38 GetError::FieldNotFound {
39 name: name.as_ref().clone(),
40 }
41 }
42
43 #[inline]
44 fn from_value_get_error(name: impl AsRef<IdStr>, error: E) -> Self {
45 skip_assert_initialized!();
46 GetError::ValueGetError {
47 name: name.as_ref().clone(),
48 error,
49 }
50 }
51}
52
53#[doc(alias = "GstStructure")]
161#[repr(transparent)]
162pub struct Structure(ptr::NonNull<ffi::GstStructure>);
163unsafe impl Send for Structure {}
164unsafe impl Sync for Structure {}
165
166impl Structure {
167 #[doc(alias = "gst_structure_new")]
168 pub fn builder(name: impl IntoGStr) -> Builder {
169 skip_assert_initialized!();
170 Builder::new(name)
171 }
172
173 #[doc(alias = "gst_structure_new_static_str_empty")]
174 pub fn builder_static(name: impl AsRef<GStr> + 'static) -> Builder {
175 skip_assert_initialized!();
176 Builder::from_static(name)
177 }
178
179 #[doc(alias = "gst_structure_new_id_str")]
180 pub fn builder_from_id(name: impl AsRef<IdStr>) -> Builder {
181 skip_assert_initialized!();
182 Builder::from_id(name)
183 }
184
185 #[doc(alias = "gst_structure_new_empty")]
197 pub fn new_empty(name: impl IntoGStr) -> Structure {
198 assert_initialized_main_thread!();
199 unsafe {
200 let ptr = name.run_with_gstr(|name| ffi::gst_structure_new_empty(name.as_ptr()));
201 debug_assert!(!ptr.is_null());
202 Structure(ptr::NonNull::new_unchecked(ptr))
203 }
204 }
205
206 #[doc(alias = "gst_structure_new_static_str_empty")]
207 pub fn new_empty_from_static(name: impl AsRef<GStr> + 'static) -> Structure {
208 assert_initialized_main_thread!();
209 unsafe {
210 cfg_if! {
211 if #[cfg(feature = "v1_26")] {
212 let ptr =
213 ffi::gst_structure_new_static_str_empty(name.as_ref().as_ptr());
214 } else {
215 let ptr = ffi::gst_structure_new_empty(name.as_ref().as_ptr());
216 }
217 }
218 debug_assert!(!ptr.is_null());
219 Structure(ptr::NonNull::new_unchecked(ptr))
220 }
221 }
222
223 #[doc(alias = "gst_structure_new_id_str_empty")]
224 pub fn new_empty_from_id(name: impl AsRef<IdStr>) -> Structure {
225 assert_initialized_main_thread!();
226 unsafe {
227 cfg_if! {
228 if #[cfg(feature = "v1_26")] {
229 let ptr = ffi::gst_structure_new_id_str_empty(name.as_ref().as_ptr());
230 } else {
231 let ptr = ffi::gst_structure_new_empty(name.as_ref().as_gstr().as_ptr());
232 }
233 }
234
235 debug_assert!(!ptr.is_null());
236 Structure(ptr::NonNull::new_unchecked(ptr))
237 }
238 }
239
240 #[allow(clippy::should_implement_trait)]
241 pub fn from_iter<S: IntoGStr>(
242 name: impl IntoGStr,
243 iter: impl IntoIterator<Item = (S, SendValue)>,
244 ) -> Structure {
245 skip_assert_initialized!();
246 let mut structure = Structure::new_empty(name);
247
248 iter.into_iter()
249 .for_each(|(f, v)| structure.set_value(f, v));
250
251 structure
252 }
253
254 #[allow(clippy::should_implement_trait)]
255 pub fn from_iter_with_static<S: AsRef<GStr> + 'static>(
256 name: impl AsRef<GStr> + 'static,
257 iter: impl IntoIterator<Item = (S, SendValue)>,
258 ) -> Structure {
259 skip_assert_initialized!();
260 let mut structure = Structure::new_empty_from_static(name);
261
262 iter.into_iter()
263 .for_each(|(f, v)| structure.set_value_with_static(f, v));
264
265 structure
266 }
267
268 #[allow(clippy::should_implement_trait)]
269 pub fn from_iter_with_id<S: AsRef<IdStr>>(
270 name: impl AsRef<IdStr>,
271 iter: impl IntoIterator<Item = (S, SendValue)>,
272 ) -> Structure {
273 skip_assert_initialized!();
274 let mut structure = Structure::new_empty_from_id(name);
275
276 iter.into_iter()
277 .for_each(|(f, v)| structure.set_value_with_id(f, v));
278
279 structure
280 }
281}
282
283impl IntoGlibPtr<*mut ffi::GstStructure> for Structure {
284 #[inline]
285 fn into_glib_ptr(self) -> *mut ffi::GstStructure {
286 let s = mem::ManuallyDrop::new(self);
287 s.0.as_ptr()
288 }
289}
290
291impl Deref for Structure {
292 type Target = StructureRef;
293
294 #[inline]
295 fn deref(&self) -> &StructureRef {
296 unsafe { &*(self.0.as_ptr() as *const StructureRef) }
297 }
298}
299
300impl DerefMut for Structure {
301 #[inline]
302 fn deref_mut(&mut self) -> &mut StructureRef {
303 unsafe { &mut *(self.0.as_ptr() as *mut StructureRef) }
304 }
305}
306
307impl AsRef<StructureRef> for Structure {
308 #[inline]
309 fn as_ref(&self) -> &StructureRef {
310 self.deref()
311 }
312}
313
314impl AsMut<StructureRef> for Structure {
315 #[inline]
316 fn as_mut(&mut self) -> &mut StructureRef {
317 self.deref_mut()
318 }
319}
320
321impl Clone for Structure {
322 #[inline]
323 fn clone(&self) -> Self {
324 unsafe {
325 let ptr = ffi::gst_structure_copy(self.0.as_ref());
326 debug_assert!(!ptr.is_null());
327 Structure(ptr::NonNull::new_unchecked(ptr))
328 }
329 }
330}
331
332impl Drop for Structure {
333 #[inline]
334 fn drop(&mut self) {
335 unsafe { ffi::gst_structure_free(self.0.as_mut()) }
336 }
337}
338
339impl fmt::Debug for Structure {
340 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
341 f.debug_tuple("Structure").field(self.as_ref()).finish()
342 }
343}
344
345impl fmt::Display for Structure {
346 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
347 f.write_str(&StructureRef::to_string(self.as_ref()))
350 }
351}
352
353impl PartialEq for Structure {
354 fn eq(&self, other: &Structure) -> bool {
355 StructureRef::eq(self, other)
356 }
357}
358
359impl Eq for Structure {}
360
361impl PartialEq<StructureRef> for Structure {
362 fn eq(&self, other: &StructureRef) -> bool {
363 StructureRef::eq(self, other)
364 }
365}
366
367impl PartialEq<Structure> for StructureRef {
368 fn eq(&self, other: &Structure) -> bool {
369 StructureRef::eq(other, self)
370 }
371}
372
373impl str::FromStr for Structure {
374 type Err = glib::BoolError;
375
376 #[doc(alias = "gst_structure_from_string")]
377 fn from_str(s: &str) -> Result<Self, Self::Err> {
378 assert_initialized_main_thread!();
379 unsafe {
380 let structure =
381 s.run_with_gstr(|s| ffi::gst_structure_from_string(s.as_ptr(), ptr::null_mut()));
382 if structure.is_null() {
383 Err(glib::bool_error!("Failed to parse structure from string"))
384 } else {
385 Ok(Self(ptr::NonNull::new_unchecked(structure)))
386 }
387 }
388 }
389}
390
391impl Borrow<StructureRef> for Structure {
392 #[inline]
393 fn borrow(&self) -> &StructureRef {
394 self.as_ref()
395 }
396}
397
398impl BorrowMut<StructureRef> for Structure {
399 #[inline]
400 fn borrow_mut(&mut self) -> &mut StructureRef {
401 self.as_mut()
402 }
403}
404
405impl ToOwned for StructureRef {
406 type Owned = Structure;
407
408 fn to_owned(&self) -> Structure {
409 unsafe {
410 let ptr = ffi::gst_structure_copy(&self.0);
411 debug_assert!(!ptr.is_null());
412 Structure(ptr::NonNull::new_unchecked(ptr))
413 }
414 }
415}
416
417impl glib::types::StaticType for Structure {
418 #[inline]
419 fn static_type() -> glib::types::Type {
420 unsafe { from_glib(ffi::gst_structure_get_type()) }
421 }
422}
423
424impl<'a> ToGlibPtr<'a, *const ffi::GstStructure> for Structure {
425 type Storage = PhantomData<&'a Self>;
426
427 #[inline]
428 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstStructure, Self> {
429 unsafe { Stash(self.0.as_ref(), PhantomData) }
430 }
431
432 #[inline]
433 fn to_glib_full(&self) -> *const ffi::GstStructure {
434 unsafe { ffi::gst_structure_copy(self.0.as_ref()) }
435 }
436}
437
438impl<'a> ToGlibPtr<'a, *mut ffi::GstStructure> for Structure {
439 type Storage = PhantomData<&'a Self>;
440
441 #[inline]
442 fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GstStructure, Self> {
443 unsafe {
444 Stash(
445 self.0.as_ref() as *const ffi::GstStructure as *mut ffi::GstStructure,
446 PhantomData,
447 )
448 }
449 }
450
451 #[inline]
452 fn to_glib_full(&self) -> *mut ffi::GstStructure {
453 unsafe { ffi::gst_structure_copy(self.0.as_ref()) }
454 }
455}
456
457impl<'a> ToGlibPtrMut<'a, *mut ffi::GstStructure> for Structure {
458 type Storage = PhantomData<&'a mut Self>;
459
460 #[inline]
461 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GstStructure, Self> {
462 unsafe { StashMut(self.0.as_mut(), PhantomData) }
463 }
464}
465
466impl FromGlibPtrNone<*const ffi::GstStructure> for Structure {
467 #[inline]
468 unsafe fn from_glib_none(ptr: *const ffi::GstStructure) -> Self {
469 unsafe {
470 debug_assert!(!ptr.is_null());
471 let ptr = ffi::gst_structure_copy(ptr);
472 debug_assert!(!ptr.is_null());
473 Structure(ptr::NonNull::new_unchecked(ptr))
474 }
475 }
476}
477
478impl FromGlibPtrNone<*mut ffi::GstStructure> for Structure {
479 #[inline]
480 unsafe fn from_glib_none(ptr: *mut ffi::GstStructure) -> Self {
481 unsafe {
482 debug_assert!(!ptr.is_null());
483 let ptr = ffi::gst_structure_copy(ptr);
484 debug_assert!(!ptr.is_null());
485 Structure(ptr::NonNull::new_unchecked(ptr))
486 }
487 }
488}
489
490impl FromGlibPtrFull<*const ffi::GstStructure> for Structure {
491 #[inline]
492 unsafe fn from_glib_full(ptr: *const ffi::GstStructure) -> Self {
493 unsafe {
494 debug_assert!(!ptr.is_null());
495 Structure(ptr::NonNull::new_unchecked(ptr as *mut ffi::GstStructure))
496 }
497 }
498}
499
500impl FromGlibPtrFull<*mut ffi::GstStructure> for Structure {
501 #[inline]
502 unsafe fn from_glib_full(ptr: *mut ffi::GstStructure) -> Self {
503 unsafe {
504 debug_assert!(!ptr.is_null());
505 Structure(ptr::NonNull::new_unchecked(ptr))
506 }
507 }
508}
509
510impl FromGlibPtrBorrow<*const ffi::GstStructure> for Structure {
511 #[inline]
512 unsafe fn from_glib_borrow(ptr: *const ffi::GstStructure) -> Borrowed<Self> {
513 unsafe { Borrowed::new(from_glib_full(ptr)) }
514 }
515}
516
517impl FromGlibPtrBorrow<*mut ffi::GstStructure> for Structure {
518 #[inline]
519 unsafe fn from_glib_borrow(ptr: *mut ffi::GstStructure) -> Borrowed<Self> {
520 unsafe { Borrowed::new(from_glib_full(ptr)) }
521 }
522}
523
524impl glib::value::ValueType for Structure {
525 type Type = Self;
526}
527
528impl glib::value::ValueTypeOptional for Structure {}
529
530unsafe impl<'a> glib::value::FromValue<'a> for Structure {
531 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
532
533 unsafe fn from_value(value: &'a glib::Value) -> Self {
534 unsafe {
535 skip_assert_initialized!();
536 from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
537 as *mut ffi::GstStructure)
538 }
539 }
540}
541
542impl glib::value::ToValue for Structure {
543 fn to_value(&self) -> glib::Value {
544 let mut value = glib::Value::for_value_type::<Self>();
545 unsafe {
546 glib::gobject_ffi::g_value_set_boxed(
547 value.to_glib_none_mut().0,
548 glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(self).0
549 as *mut _,
550 )
551 }
552 value
553 }
554
555 fn value_type(&self) -> glib::Type {
556 Self::static_type()
557 }
558}
559
560impl glib::value::ToValueOptional for Structure {
561 fn to_value_optional(s: Option<&Self>) -> glib::Value {
562 skip_assert_initialized!();
563 let mut value = glib::Value::for_value_type::<Self>();
564 unsafe {
565 glib::gobject_ffi::g_value_set_boxed(
566 value.to_glib_none_mut().0,
567 glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(&s).0
568 as *mut _,
569 )
570 }
571 value
572 }
573}
574
575impl From<Structure> for glib::Value {
576 fn from(v: Structure) -> glib::Value {
577 skip_assert_initialized!();
578 let mut value = glib::Value::for_value_type::<Structure>();
579 unsafe {
580 glib::gobject_ffi::g_value_take_boxed(
581 value.to_glib_none_mut().0,
582 glib::translate::IntoGlibPtr::<*mut ffi::GstStructure>::into_glib_ptr(v) as *mut _,
583 )
584 }
585 value
586 }
587}
588
589impl GlibPtrDefault for Structure {
590 type GlibType = *mut ffi::GstStructure;
591}
592
593unsafe impl TransparentPtrType for Structure {}
594
595#[repr(transparent)]
596#[doc(alias = "GstStructure")]
597pub struct StructureRef(ffi::GstStructure);
598
599unsafe impl Send for StructureRef {}
600unsafe impl Sync for StructureRef {}
601
602impl StructureRef {
603 #[inline]
604 pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstStructure) -> &'a StructureRef {
605 unsafe {
606 debug_assert!(!ptr.is_null());
607
608 &*(ptr as *mut StructureRef)
609 }
610 }
611
612 #[inline]
613 pub unsafe fn from_glib_borrow_mut<'a>(ptr: *mut ffi::GstStructure) -> &'a mut StructureRef {
614 unsafe {
615 debug_assert!(!ptr.is_null());
616 #[cfg(feature = "v1_28")]
617 debug_assert_ne!(ffi::gst_structure_is_writable(ptr), glib::ffi::GFALSE,);
618
619 &mut *(ptr as *mut StructureRef)
620 }
621 }
622
623 #[inline]
624 pub fn as_ptr(&self) -> *const ffi::GstStructure {
625 self as *const Self as *const ffi::GstStructure
626 }
627
628 #[inline]
629 pub fn as_mut_ptr(&self) -> *mut ffi::GstStructure {
630 self as *const Self as *mut ffi::GstStructure
631 }
632
633 #[doc(alias = "gst_structure_get")]
634 pub fn get<'a, T: FromValue<'a>>(
635 &'a self,
636 name: impl IntoGStr,
637 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
638 {
639 name.run_with_gstr(|name| {
640 self.value(name)
641 .map_err(|err| match err {
642 GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
643 _ => unreachable!(),
644 })?
645 .get()
646 .map_err(|err| GetError::from_value_get_error(IdStr::from(name), err))
647 })
648 }
649
650 #[doc(alias = "gst_structure_id_str_get")]
651 #[inline]
652 pub fn get_by_id<'a, T: FromValue<'a>>(
653 &'a self,
654 name: impl AsRef<IdStr>,
655 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
656 {
657 self.value_by_id(name.as_ref())
658 .map_err(|err| match err {
659 GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
660 _ => unreachable!(),
661 })?
662 .get()
663 .map_err(|err| GetError::from_value_get_error(name, err))
664 }
665
666 #[doc(alias = "gst_structure_get")]
667 pub fn get_optional<'a, T: FromValue<'a>>(
668 &'a self,
669 name: impl IntoGStr,
670 ) -> Result<
671 Option<T>,
672 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
673 > {
674 name.run_with_gstr(|name| {
675 self.value(name)
676 .ok()
677 .map(|v| v.get())
678 .transpose()
679 .map_err(|err| GetError::from_value_get_error(IdStr::from(name), err))
680 })
681 }
682
683 #[doc(alias = "gst_structure_id_str_get")]
684 pub fn get_optional_by_id<'a, T: FromValue<'a>>(
685 &'a self,
686 name: impl AsRef<IdStr>,
687 ) -> Result<
688 Option<T>,
689 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
690 > {
691 self.value_by_id(name.as_ref())
692 .ok()
693 .map(|v| v.get())
694 .transpose()
695 .map_err(|err| GetError::from_value_get_error(name, err))
696 }
697
698 #[doc(alias = "get_value")]
699 #[doc(alias = "gst_structure_get_value")]
700 pub fn value(
701 &self,
702 name: impl IntoGStr,
703 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
704 unsafe {
705 name.run_with_gstr(|name| {
706 let value = ffi::gst_structure_get_value(&self.0, name.as_ptr());
707
708 if value.is_null() {
709 return Err(GetError::new_field_not_found(IdStr::from(name)));
710 }
711
712 Ok(&*(value as *const SendValue))
713 })
714 }
715 }
716
717 #[doc(alias = "gst_structure_id_str_get_value")]
718 pub fn value_by_id(
719 &self,
720 name: impl AsRef<IdStr>,
721 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
722 unsafe {
723 cfg_if! {
724 if #[cfg(feature = "v1_26")] {
725 let value = ffi::gst_structure_id_str_get_value(&self.0, name.as_ref().as_ptr());
726 } else {
727 let value = ffi::gst_structure_get_value(&self.0, name.as_ref().as_gstr().as_ptr());
728 }
729 }
730
731 if value.is_null() {
732 return Err(GetError::new_field_not_found(name));
733 }
734
735 Ok(&*(value as *const SendValue))
736 }
737 }
738
739 #[deprecated = "use `get_by_id()` instead"]
740 #[allow(deprecated)]
741 #[doc(alias = "gst_structure_id_get")]
742 pub fn get_by_quark<'a, T: FromValue<'a>>(
743 &'a self,
744 name: glib::Quark,
745 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
746 {
747 self.value_by_quark(name)
748 .map_err(|err| match err {
749 GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
750 _ => unreachable!(),
751 })?
752 .get()
753 .map_err(|err| GetError::from_value_get_error(IdStr::from(name.as_str()), err))
754 }
755
756 #[deprecated = "use `get_optional_by_id()` instead"]
757 #[allow(deprecated)]
758 #[doc(alias = "gst_structure_id_get")]
759 pub fn get_optional_by_quark<'a, T: FromValue<'a>>(
760 &'a self,
761 name: glib::Quark,
762 ) -> Result<
763 Option<T>,
764 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
765 > {
766 self.value_by_quark(name)
767 .ok()
768 .map(|v| v.get())
769 .transpose()
770 .map_err(|err| GetError::from_value_get_error(IdStr::from(name.as_str()), err))
771 }
772
773 #[deprecated = "use `value_by_id()` instead"]
774 #[doc(alias = "gst_structure_id_get_value")]
775 pub fn value_by_quark(
776 &self,
777 name: glib::Quark,
778 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
779 unsafe {
780 let value = ffi::gst_structure_id_get_value(&self.0, name.into_glib());
781
782 if value.is_null() {
783 return Err(GetError::new_field_not_found(IdStr::from(name.as_str())));
784 }
785
786 Ok(&*(value as *const SendValue))
787 }
788 }
789
790 #[doc(alias = "gst_structure_set")]
795 pub fn set(&mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) {
796 let value = glib::SendValue::from_owned(value);
797 self.set_value(name, value);
798 }
799
800 #[doc(alias = "gst_structure_set_static_str")]
805 pub fn set_with_static(
806 &mut self,
807 name: impl AsRef<GStr> + 'static,
808 value: impl Into<glib::Value> + Send,
809 ) {
810 let value = glib::SendValue::from_owned(value);
811 self.set_value_with_static(name, value);
812 }
813
814 #[doc(alias = "gst_structure_id_str_set")]
819 pub fn set_with_id(&mut self, name: impl AsRef<IdStr>, value: impl Into<glib::Value> + Send) {
820 let value = glib::SendValue::from_owned(value);
821 self.set_value_with_id(name, value);
822 }
823
824 #[doc(alias = "gst_structure_set")]
830 pub fn set_if(
831 &mut self,
832 name: impl IntoGStr,
833 value: impl Into<glib::Value> + Send,
834 predicate: bool,
835 ) {
836 if predicate {
837 self.set(name, value);
838 }
839 }
840
841 #[doc(alias = "gst_structure_set_static_str")]
847 pub fn set_with_static_if(
848 &mut self,
849 name: impl AsRef<GStr> + 'static,
850 value: impl Into<glib::Value> + Send,
851 predicate: bool,
852 ) {
853 if predicate {
854 self.set_with_static(name, value);
855 }
856 }
857
858 #[doc(alias = "gst_structure_id_str_set")]
864 pub fn set_with_id_if(
865 &mut self,
866 name: impl AsRef<IdStr>,
867 value: impl Into<glib::Value> + Send,
868 predicate: bool,
869 ) {
870 if predicate {
871 self.set_with_id(name, value);
872 }
873 }
874
875 #[doc(alias = "gst_structure_set")]
880 pub fn set_if_some(
881 &mut self,
882 name: impl IntoGStr,
883 value: Option<impl Into<glib::Value> + Send>,
884 ) {
885 if let Some(value) = value {
886 self.set(name, value);
887 }
888 }
889
890 #[doc(alias = "gst_structure_set_static_str")]
895 pub fn set_with_static_if_some(
896 &mut self,
897 name: impl AsRef<GStr> + 'static,
898 value: Option<impl Into<glib::Value> + Send>,
899 ) {
900 if let Some(value) = value {
901 self.set_with_static(name, value);
902 }
903 }
904
905 #[doc(alias = "gst_structure_id_str_set")]
910 pub fn set_with_id_if_some(
911 &mut self,
912 name: impl AsRef<IdStr>,
913 value: Option<impl Into<glib::Value> + Send>,
914 ) {
915 if let Some(value) = value {
916 self.set_with_id(name, value);
917 }
918 }
919
920 #[inline]
925 pub fn set_from_iter<
926 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
927 I: ToSendValue,
928 >(
929 &mut self,
930 name: impl IntoGStr,
931 iter: impl IntoIterator<Item = I>,
932 ) {
933 let iter = iter.into_iter().map(|item| item.to_send_value());
934 self.set(name, V::from_iter(iter));
935 }
936
937 #[inline]
942 pub fn set_with_static_from_iter<
943 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
944 I: ToSendValue,
945 >(
946 &mut self,
947 name: impl AsRef<GStr> + 'static,
948 iter: impl IntoIterator<Item = I>,
949 ) {
950 let iter = iter.into_iter().map(|item| item.to_send_value());
951 self.set_with_static(name, V::from_iter(iter));
952 }
953
954 #[inline]
959 pub fn set_with_id_from_iter<
960 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
961 I: ToSendValue,
962 >(
963 &mut self,
964 name: impl AsRef<IdStr>,
965 iter: impl IntoIterator<Item = I>,
966 ) {
967 let iter = iter.into_iter().map(|item| item.to_send_value());
968 self.set_with_id(name, V::from_iter(iter));
969 }
970
971 #[inline]
977 pub fn set_if_not_empty<
978 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
979 I: ToSendValue,
980 >(
981 &mut self,
982 name: impl IntoGStr,
983 iter: impl IntoIterator<Item = I>,
984 ) {
985 let mut iter = iter.into_iter().peekable();
986 if iter.peek().is_some() {
987 let iter = iter.map(|item| item.to_send_value());
988 self.set(name, V::from_iter(iter));
989 }
990 }
991
992 #[inline]
998 pub fn set_with_static_if_not_empty<
999 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
1000 I: ToSendValue,
1001 >(
1002 &mut self,
1003 name: impl AsRef<GStr> + 'static,
1004 iter: impl IntoIterator<Item = I>,
1005 ) {
1006 let mut iter = iter.into_iter().peekable();
1007 if iter.peek().is_some() {
1008 let iter = iter.map(|item| item.to_send_value());
1009 self.set_with_static(name, V::from_iter(iter));
1010 }
1011 }
1012
1013 #[inline]
1019 pub fn set_with_id_if_not_empty<
1020 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
1021 I: ToSendValue,
1022 >(
1023 &mut self,
1024 name: impl AsRef<IdStr>,
1025 iter: impl IntoIterator<Item = I>,
1026 ) {
1027 let mut iter = iter.into_iter().peekable();
1028 if iter.peek().is_some() {
1029 let iter = iter.map(|item| item.to_send_value());
1030 self.set_with_id(name, V::from_iter(iter));
1031 }
1032 }
1033
1034 #[doc(alias = "gst_structure_set_value")]
1039 pub fn set_value(&mut self, name: impl IntoGStr, value: SendValue) {
1040 unsafe {
1041 name.run_with_gstr(|name| {
1042 ffi::gst_structure_take_value(&mut self.0, name.as_ptr(), &mut value.into_raw())
1043 });
1044 }
1045 }
1046
1047 #[doc(alias = "gst_structure_set_value_static_str")]
1052 pub fn set_value_with_static(&mut self, name: impl AsRef<GStr> + 'static, value: SendValue) {
1053 unsafe {
1054 cfg_if! {
1055 if #[cfg(feature = "v1_26")] {
1056 ffi::gst_structure_take_value_static_str(
1057 &mut self.0,
1058 name.as_ref().as_ptr(),
1059 &mut value.into_raw(),
1060 )
1061 } else {
1062 ffi::gst_structure_take_value(
1063 &mut self.0,
1064 name.as_ref().as_ptr(),
1065 &mut value.into_raw(),
1066 )
1067 }
1068 }
1069 }
1070 }
1071
1072 #[doc(alias = "gst_structure_id_str_set_value")]
1077 pub fn set_value_with_id(&mut self, name: impl AsRef<IdStr>, value: SendValue) {
1078 unsafe {
1079 cfg_if! {
1080 if #[cfg(feature = "v1_26")] {
1081 ffi::gst_structure_id_str_take_value(
1082 &mut self.0,
1083 name.as_ref().as_ptr(),
1084 &mut value.into_raw(),
1085 )
1086 } else {
1087 ffi::gst_structure_take_value(
1088 &mut self.0,
1089 name.as_ref().as_gstr().as_ptr(),
1090 &mut value.into_raw(),
1091 )
1092 }
1093 }
1094 }
1095 }
1096
1097 #[doc(alias = "gst_structure_set_value")]
1103 pub fn set_value_if(&mut self, name: impl IntoGStr, value: SendValue, predicate: bool) {
1104 if predicate {
1105 self.set_value(name, value);
1106 }
1107 }
1108
1109 #[doc(alias = "gst_structure_set_value_static_str")]
1115 pub fn set_value_with_static_if(
1116 &mut self,
1117 name: impl AsRef<GStr> + 'static,
1118 value: SendValue,
1119 predicate: bool,
1120 ) {
1121 if predicate {
1122 self.set_value_with_static(name, value);
1123 }
1124 }
1125
1126 #[doc(alias = "gst_structure_id_str_set_value")]
1132 pub fn set_value_with_id_if(
1133 &mut self,
1134 name: impl AsRef<IdStr>,
1135 value: SendValue,
1136 predicate: bool,
1137 ) {
1138 if predicate {
1139 self.set_value_with_id(name, value);
1140 }
1141 }
1142
1143 #[doc(alias = "gst_structure_set_value")]
1148 pub fn set_value_if_some(&mut self, name: impl IntoGStr, value: Option<SendValue>) {
1149 if let Some(value) = value {
1150 self.set_value(name, value);
1151 }
1152 }
1153
1154 #[doc(alias = "gst_structure_set_value_static_str")]
1159 pub fn set_value_with_static_if_some(
1160 &mut self,
1161 name: impl AsRef<GStr> + 'static,
1162 value: Option<SendValue>,
1163 ) {
1164 if let Some(value) = value {
1165 self.set_value_with_static(name, value);
1166 }
1167 }
1168
1169 #[doc(alias = "gst_structure_id_str_set_value")]
1174 pub fn set_value_with_id_if_some(&mut self, name: impl AsRef<IdStr>, value: Option<SendValue>) {
1175 if let Some(value) = value {
1176 self.set_value_with_id(name, value);
1177 }
1178 }
1179
1180 #[deprecated = "use `set_by_id()` instead"]
1181 #[allow(deprecated)]
1182 #[doc(alias = "gst_structure_id_set")]
1183 pub fn set_by_quark(&mut self, name: glib::Quark, value: impl Into<glib::Value> + Send) {
1184 let value = glib::SendValue::from_owned(value);
1185 self.set_value_by_quark(name, value);
1186 }
1187
1188 #[deprecated = "use `set_by_id_if_some()` instead"]
1189 #[allow(deprecated)]
1190 #[doc(alias = "gst_structure_id_set")]
1191 pub fn set_by_quark_if_some(
1192 &mut self,
1193 name: glib::Quark,
1194 value: Option<impl Into<glib::Value> + Send>,
1195 ) {
1196 if let Some(value) = value {
1197 self.set_by_quark(name, value);
1198 }
1199 }
1200
1201 #[deprecated = "use `set_by_id_value()` instead"]
1202 #[doc(alias = "gst_structure_id_set_value")]
1203 pub fn set_value_by_quark(&mut self, name: glib::Quark, value: SendValue) {
1204 unsafe {
1205 ffi::gst_structure_id_take_value(&mut self.0, name.into_glib(), &mut value.into_raw());
1206 }
1207 }
1208
1209 #[deprecated = "use `set_by_id_value_if_some()` instead"]
1210 #[allow(deprecated)]
1211 #[doc(alias = "gst_structure_id_set_value")]
1212 pub fn set_value_by_quark_if_some(&mut self, name: glib::Quark, value: Option<SendValue>) {
1213 if let Some(value) = value {
1214 self.set_value_by_quark(name, value);
1215 }
1216 }
1217
1218 #[doc(alias = "get_name")]
1219 #[doc(alias = "gst_structure_get_name")]
1220 pub fn name(&self) -> &glib::GStr {
1221 unsafe { glib::GStr::from_ptr(ffi::gst_structure_get_name(&self.0)) }
1222 }
1223
1224 #[cfg(feature = "v1_26")]
1225 #[doc(alias = "get_name")]
1226 #[doc(alias = "gst_structure_get_name_id_str")]
1227 pub fn name_id(&self) -> &IdStr {
1228 unsafe { &*(ffi::gst_structure_get_name_id_str(&self.0) as *const crate::IdStr) }
1229 }
1230
1231 #[deprecated = "use `name()` instead, or `name_id()` with feature v1_26"]
1232 #[doc(alias = "gst_structure_get_name_id")]
1233 pub fn name_quark(&self) -> glib::Quark {
1234 unsafe { from_glib(ffi::gst_structure_get_name_id(&self.0)) }
1235 }
1236
1237 #[doc(alias = "gst_structure_set_name")]
1238 pub fn set_name(&mut self, name: impl IntoGStr) {
1239 unsafe {
1240 name.run_with_gstr(|name| ffi::gst_structure_set_name(&mut self.0, name.as_ptr()))
1241 }
1242 }
1243
1244 #[doc(alias = "gst_structure_set_name_static_str")]
1245 pub fn set_name_from_static(&mut self, name: impl AsRef<GStr> + 'static) {
1246 unsafe {
1247 cfg_if! {
1248 if #[cfg(feature = "v1_26")] {
1249 ffi::gst_structure_set_name_static_str(
1250 &mut self.0,
1251 name.as_ref().as_ptr(),
1252 )
1253 } else {
1254 ffi::gst_structure_set_name(&mut self.0, name.as_ref().as_ptr())
1255 }
1256 }
1257 }
1258 }
1259
1260 #[doc(alias = "gst_structure_set_name_id_str")]
1261 pub fn set_name_from_id(&mut self, name: impl AsRef<IdStr>) {
1262 unsafe {
1263 cfg_if! {
1264 if #[cfg(feature = "v1_26")] {
1265 ffi::gst_structure_set_name_id_str(
1266 &mut self.0,
1267 name.as_ref().as_ptr(),
1268 )
1269 } else {
1270 ffi::gst_structure_set_name(&mut self.0, name.as_ref().as_gstr().as_ptr())
1271 }
1272 }
1273 }
1274 }
1275
1276 #[doc(alias = "gst_structure_set_name")]
1277 pub fn set_name_if_some(&mut self, name: Option<impl IntoGStr>) {
1278 if let Some(name) = name {
1279 self.set_name(name);
1280 }
1281 }
1282
1283 #[doc(alias = "gst_structure_set_name_static_str")]
1284 pub fn set_name_from_static_if_some(&mut self, name: Option<impl AsRef<GStr> + 'static>) {
1285 if let Some(name) = name {
1286 self.set_name_from_static(name);
1287 }
1288 }
1289
1290 #[doc(alias = "gst_structure_set_name_id_str")]
1291 pub fn set_name_from_id_if_some(&mut self, name: Option<impl AsRef<IdStr>>) {
1292 if let Some(name) = name {
1293 self.set_name_from_id(name);
1294 }
1295 }
1296
1297 #[doc(alias = "gst_structure_has_name")]
1298 pub fn has_name(&self, name: &str) -> bool {
1299 self.name() == name
1300 }
1301
1302 #[doc(alias = "gst_structure_has_field")]
1303 pub fn has_field(&self, field: impl IntoGStr) -> bool {
1304 unsafe {
1305 field.run_with_gstr(|field| {
1306 from_glib(ffi::gst_structure_has_field(&self.0, field.as_ptr()))
1307 })
1308 }
1309 }
1310
1311 #[doc(alias = "gst_structure_id_str_has_field")]
1312 pub fn has_field_by_id(&self, field: impl AsRef<IdStr>) -> bool {
1313 unsafe {
1314 cfg_if! {
1315 if #[cfg(feature = "v1_26")] {
1316 from_glib(ffi::gst_structure_id_str_has_field(
1317 &self.0,
1318 field.as_ref().as_ptr(),
1319 ))
1320 } else {
1321 from_glib(ffi::gst_structure_has_field(
1322 &self.0,
1323 field.as_ref().as_gstr().as_ptr(),
1324 ))
1325 }
1326 }
1327 }
1328 }
1329
1330 #[doc(alias = "gst_structure_has_field_typed")]
1331 pub fn has_field_with_type(&self, field: impl IntoGStr, type_: glib::Type) -> bool {
1332 unsafe {
1333 field.run_with_gstr(|field| {
1334 from_glib(ffi::gst_structure_has_field_typed(
1335 &self.0,
1336 field.as_ptr(),
1337 type_.into_glib(),
1338 ))
1339 })
1340 }
1341 }
1342
1343 #[doc(alias = "gst_structure_id_str_has_field_typed")]
1344 pub fn has_field_with_type_by_id(&self, field: impl AsRef<IdStr>, type_: glib::Type) -> bool {
1345 unsafe {
1346 cfg_if! {
1347 if #[cfg(feature = "v1_26")] {
1348 from_glib(ffi::gst_structure_id_str_has_field_typed(
1349 &self.0,
1350 field.as_ref().as_ptr(),
1351 type_.into_glib(),
1352 ))
1353 } else {
1354 from_glib(ffi::gst_structure_has_field_typed(
1355 &self.0,
1356 field.as_ref().as_gstr().as_ptr(),
1357 type_.into_glib(),
1358 ))
1359 }
1360 }
1361 }
1362 }
1363
1364 #[deprecated = "use `has_field_by_id()`"]
1365 #[doc(alias = "gst_structure_id_has_field")]
1366 pub fn has_field_by_quark(&self, field: glib::Quark) -> bool {
1367 unsafe { from_glib(ffi::gst_structure_id_has_field(&self.0, field.into_glib())) }
1368 }
1369
1370 #[deprecated = "use `has_field_with_type_by_id()`"]
1371 #[doc(alias = "gst_structure_id_has_field_typed")]
1372 pub fn has_field_with_type_by_quark(&self, field: glib::Quark, type_: glib::Type) -> bool {
1373 unsafe {
1374 from_glib(ffi::gst_structure_id_has_field_typed(
1375 &self.0,
1376 field.into_glib(),
1377 type_.into_glib(),
1378 ))
1379 }
1380 }
1381
1382 #[doc(alias = "gst_structure_remove_field")]
1383 pub fn remove_field(&mut self, field: impl IntoGStr) {
1384 unsafe {
1385 field.run_with_gstr(|field| {
1386 ffi::gst_structure_remove_field(&mut self.0, field.as_ptr())
1387 });
1388 }
1389 }
1390
1391 #[doc(alias = "gst_structure_remove_fields")]
1392 pub fn remove_fields<S: IntoGStr>(&mut self, fields: impl IntoIterator<Item = S>) {
1393 for f in fields.into_iter() {
1394 self.remove_field(f)
1395 }
1396 }
1397
1398 #[doc(alias = "gst_structure_id_str_remove_field")]
1399 pub fn remove_field_by_id(&mut self, field: impl AsRef<IdStr>) {
1400 unsafe {
1401 cfg_if! {
1402 if #[cfg(feature = "v1_26")] {
1403 ffi::gst_structure_id_str_remove_field(&mut self.0, field.as_ref().as_ptr())
1404 } else {
1405 ffi::gst_structure_remove_field(&mut self.0, field.as_ref().as_gstr().as_ptr())
1406 }
1407 }
1408 }
1409 }
1410
1411 #[doc(alias = "gst_structure_id_str_remove_fields")]
1412 pub fn remove_field_by_ids<S: AsRef<IdStr>>(&mut self, fields: impl IntoIterator<Item = S>) {
1413 for f in fields.into_iter() {
1414 self.remove_field_by_id(f)
1415 }
1416 }
1417
1418 #[doc(alias = "gst_structure_remove_all_fields")]
1419 pub fn remove_all_fields(&mut self) {
1420 unsafe {
1421 ffi::gst_structure_remove_all_fields(&mut self.0);
1422 }
1423 }
1424
1425 pub fn fields(&self) -> FieldIterator<'_> {
1426 FieldIterator::new(self)
1427 }
1428
1429 pub fn iter(&self) -> Iter<'_> {
1430 Iter::new(self)
1431 }
1432
1433 #[cfg(feature = "v1_26")]
1434 pub fn field_ids(&self) -> FieldIdIterator<'_> {
1435 FieldIdIterator::new(self)
1436 }
1437
1438 #[cfg(feature = "v1_26")]
1439 pub fn id_iter(&self) -> IdIter<'_> {
1440 IdIter::new(self)
1441 }
1442
1443 #[doc(alias = "get_nth_field_name")]
1444 #[doc(alias = "gst_structure_nth_field_name")]
1445 pub fn nth_field_name(&self, idx: usize) -> Option<&glib::GStr> {
1446 if idx >= self.n_fields() {
1447 return None;
1448 }
1449
1450 unsafe {
1451 let field_name = ffi::gst_structure_nth_field_name(&self.0, idx as u32);
1452 debug_assert!(!field_name.is_null());
1453
1454 Some(glib::GStr::from_ptr(field_name))
1455 }
1456 }
1457
1458 #[cfg(feature = "v1_26")]
1459 #[doc(alias = "get_nth_field_name")]
1460 #[doc(alias = "gst_structure_id_str_nth_field_name")]
1461 pub fn nth_field_by_id(&self, idx: usize) -> Option<&IdStr> {
1462 if idx >= self.n_fields() {
1463 return None;
1464 }
1465
1466 unsafe {
1467 let field_name = ffi::gst_structure_id_str_nth_field_name(&self.0, idx as u32);
1468 debug_assert!(!field_name.is_null());
1469
1470 Some(&*(field_name as *const crate::IdStr))
1471 }
1472 }
1473
1474 #[doc(alias = "gst_structure_n_fields")]
1475 pub fn n_fields(&self) -> usize {
1476 unsafe { ffi::gst_structure_n_fields(&self.0) as usize }
1477 }
1478
1479 pub fn len(&self) -> usize {
1480 self.n_fields()
1481 }
1482
1483 pub fn is_empty(&self) -> bool {
1484 self.n_fields() == 0
1485 }
1486
1487 #[doc(alias = "gst_structure_can_intersect")]
1488 pub fn can_intersect(&self, other: &StructureRef) -> bool {
1489 unsafe { from_glib(ffi::gst_structure_can_intersect(&self.0, &other.0)) }
1490 }
1491
1492 #[doc(alias = "gst_structure_intersect")]
1493 pub fn intersect(&self, other: &StructureRef) -> Option<Structure> {
1494 unsafe { from_glib_full(ffi::gst_structure_intersect(&self.0, &other.0)) }
1495 }
1496
1497 #[doc(alias = "gst_structure_is_subset")]
1498 pub fn is_subset(&self, superset: &StructureRef) -> bool {
1499 unsafe { from_glib(ffi::gst_structure_is_subset(&self.0, &superset.0)) }
1500 }
1501
1502 #[doc(alias = "gst_structure_fixate")]
1503 pub fn fixate(&mut self) {
1504 unsafe { ffi::gst_structure_fixate(&mut self.0) }
1505 }
1506
1507 #[doc(alias = "gst_structure_fixate_field")]
1508 pub fn fixate_field(&mut self, name: impl IntoGStr) -> bool {
1509 unsafe {
1510 name.run_with_gstr(|name| {
1511 from_glib(ffi::gst_structure_fixate_field(&mut self.0, name.as_ptr()))
1512 })
1513 }
1514 }
1515
1516 #[doc(alias = "gst_structure_fixate_field_boolean")]
1517 pub fn fixate_field_bool(&mut self, name: impl IntoGStr, target: bool) -> bool {
1518 unsafe {
1519 name.run_with_gstr(|name| {
1520 from_glib(ffi::gst_structure_fixate_field_boolean(
1521 &mut self.0,
1522 name.as_ptr(),
1523 target.into_glib(),
1524 ))
1525 })
1526 }
1527 }
1528
1529 #[doc(alias = "gst_structure_fixate_field_string")]
1530 pub fn fixate_field_str(&mut self, name: impl IntoGStr, target: impl IntoGStr) -> bool {
1531 unsafe {
1532 name.run_with_gstr(|name| {
1533 target.run_with_gstr(|target| {
1534 from_glib(ffi::gst_structure_fixate_field_string(
1535 &mut self.0,
1536 name.as_ptr(),
1537 target.as_ptr(),
1538 ))
1539 })
1540 })
1541 }
1542 }
1543
1544 #[doc(alias = "gst_structure_fixate_field_nearest_double")]
1545 pub fn fixate_field_nearest_double(&mut self, name: impl IntoGStr, target: f64) -> bool {
1546 unsafe {
1547 name.run_with_gstr(|name| {
1548 from_glib(ffi::gst_structure_fixate_field_nearest_double(
1549 &mut self.0,
1550 name.as_ptr(),
1551 target,
1552 ))
1553 })
1554 }
1555 }
1556
1557 #[doc(alias = "gst_structure_fixate_field_nearest_fraction")]
1558 pub fn fixate_field_nearest_fraction(
1559 &mut self,
1560 name: impl IntoGStr,
1561 target: impl Into<Fraction>,
1562 ) -> bool {
1563 skip_assert_initialized!();
1564
1565 let target = target.into();
1566 unsafe {
1567 name.run_with_gstr(|name| {
1568 from_glib(ffi::gst_structure_fixate_field_nearest_fraction(
1569 &mut self.0,
1570 name.as_ptr(),
1571 target.numer(),
1572 target.denom(),
1573 ))
1574 })
1575 }
1576 }
1577
1578 #[doc(alias = "gst_structure_fixate_field_nearest_int")]
1579 pub fn fixate_field_nearest_int(&mut self, name: impl IntoGStr, target: i32) -> bool {
1580 unsafe {
1581 name.run_with_gstr(|name| {
1582 from_glib(ffi::gst_structure_fixate_field_nearest_int(
1583 &mut self.0,
1584 name.as_ptr(),
1585 target,
1586 ))
1587 })
1588 }
1589 }
1590
1591 #[cfg(feature = "v1_20")]
1592 #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
1593 #[doc(alias = "gst_structure_serialize")]
1594 pub fn serialize(&self, flags: crate::SerializeFlags) -> glib::GString {
1595 unsafe { from_glib_full(ffi::gst_structure_serialize(&self.0, flags.into_glib())) }
1596 }
1597
1598 #[cfg(feature = "v1_24")]
1599 #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1600 #[doc(alias = "gst_structure_serialize")]
1601 #[doc(alias = "gst_structure_serialize_full")]
1602 pub fn serialize_strict(
1603 &self,
1604 flags: crate::SerializeFlags,
1605 ) -> Result<glib::GString, glib::BoolError> {
1606 unsafe {
1607 let res = ffi::gst_structure_serialize_full(
1608 &self.0,
1609 flags.into_glib() | ffi::GST_SERIALIZE_FLAG_STRICT,
1610 );
1611 if res.is_null() {
1612 Err(glib::bool_error!("Failed to serialize structure to string"))
1613 } else {
1614 Ok(from_glib_full(res))
1615 }
1616 }
1617 }
1618
1619 #[deprecated = "Use `iter()` instead, or `id_iter()` with feature v1_26"]
1620 #[doc(alias = "gst_structure_foreach")]
1621 pub fn foreach<F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>>(
1622 &self,
1623 mut func: F,
1624 ) -> bool {
1625 unsafe {
1626 unsafe extern "C" fn trampoline<
1627 F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>,
1628 >(
1629 quark: glib::ffi::GQuark,
1630 value: *const glib::gobject_ffi::GValue,
1631 user_data: glib::ffi::gpointer,
1632 ) -> glib::ffi::gboolean {
1633 unsafe {
1634 let func = &mut *(user_data as *mut F);
1635 let res = func(from_glib(quark), &*(value as *const glib::Value));
1636
1637 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1638 }
1639 }
1640 let func = &mut func as *mut F;
1641 from_glib(ffi::gst_structure_foreach(
1642 self.as_ptr(),
1643 Some(trampoline::<F>),
1644 func as glib::ffi::gpointer,
1645 ))
1646 }
1647 }
1648
1649 #[cfg(feature = "v1_26")]
1650 #[doc(alias = "gst_structure_map_in_place_id_str")]
1653 pub fn map_in_place_by_id<F: FnMut(&IdStr, &mut glib::Value) -> std::ops::ControlFlow<()>>(
1654 &mut self,
1655 mut func: F,
1656 ) {
1657 unsafe {
1658 unsafe extern "C" fn trampoline<
1659 F: FnMut(&IdStr, &mut glib::Value) -> std::ops::ControlFlow<()>,
1660 >(
1661 fieldname: *const ffi::GstIdStr,
1662 value: *mut glib::gobject_ffi::GValue,
1663 user_data: glib::ffi::gpointer,
1664 ) -> glib::ffi::gboolean {
1665 unsafe {
1666 let func = &mut *(user_data as *mut F);
1667 let res = func(
1668 &*(fieldname as *const IdStr),
1669 &mut *(value as *mut glib::Value),
1670 );
1671
1672 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1673 }
1674 }
1675 let func = &mut func as *mut F;
1676 let _ = ffi::gst_structure_map_in_place_id_str(
1677 self.as_mut_ptr(),
1678 Some(trampoline::<F>),
1679 func as glib::ffi::gpointer,
1680 );
1681 }
1682 }
1683
1684 #[cfg(feature = "v1_26")]
1685 #[doc(alias = "gst_structure_filter_and_map_in_place_id_str")]
1692 pub fn filter_map_in_place_by_id<F: FnMut(&IdStr, glib::Value) -> Option<glib::Value>>(
1693 &mut self,
1694 mut func: F,
1695 ) {
1696 unsafe {
1697 unsafe extern "C" fn trampoline<
1698 F: FnMut(&IdStr, glib::Value) -> Option<glib::Value>,
1699 >(
1700 fieldname: *const ffi::GstIdStr,
1701 value: *mut glib::gobject_ffi::GValue,
1702 user_data: glib::ffi::gpointer,
1703 ) -> glib::ffi::gboolean {
1704 unsafe {
1705 let func = &mut *(user_data as *mut F);
1706
1707 let v = mem::replace(
1708 &mut *(value as *mut glib::Value),
1709 glib::Value::uninitialized(),
1710 );
1711 match func(&*(fieldname as *const IdStr), v) {
1712 None => glib::ffi::GFALSE,
1713 Some(v) => {
1714 *value = v.into_raw();
1715 glib::ffi::GTRUE
1716 }
1717 }
1718 }
1719 }
1720
1721 let func = &mut func as *mut F;
1722 ffi::gst_structure_filter_and_map_in_place_id_str(
1723 self.as_mut_ptr(),
1724 Some(trampoline::<F>),
1725 func as glib::ffi::gpointer,
1726 );
1727 }
1728 }
1729
1730 #[doc(alias = "gst_structure_map_in_place")]
1745 pub fn map_in_place<F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>>(
1746 &mut self,
1747 mut func: F,
1748 ) -> std::ops::ControlFlow<()> {
1749 unsafe {
1750 unsafe extern "C" fn trampoline<
1751 F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>,
1752 >(
1753 quark: glib::ffi::GQuark,
1754 value: *mut glib::gobject_ffi::GValue,
1755 user_data: glib::ffi::gpointer,
1756 ) -> glib::ffi::gboolean {
1757 unsafe {
1758 let func = &mut *(user_data as *mut F);
1759 let res = func(from_glib(quark), &mut *(value as *mut glib::Value));
1760
1761 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1762 }
1763 }
1764 let func = &mut func as *mut F;
1765 if from_glib(ffi::gst_structure_map_in_place(
1766 self.as_mut_ptr(),
1767 Some(trampoline::<F>),
1768 func as glib::ffi::gpointer,
1769 )) {
1770 std::ops::ControlFlow::Continue(())
1771 } else {
1772 std::ops::ControlFlow::Break(())
1773 }
1774 }
1775 }
1776
1777 #[doc(alias = "gst_structure_filter_and_map_in_place")]
1790 pub fn filter_map_in_place<F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>>(
1791 &mut self,
1792 mut func: F,
1793 ) {
1794 unsafe {
1795 unsafe extern "C" fn trampoline<
1796 F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>,
1797 >(
1798 quark: glib::ffi::GQuark,
1799 value: *mut glib::gobject_ffi::GValue,
1800 user_data: glib::ffi::gpointer,
1801 ) -> glib::ffi::gboolean {
1802 unsafe {
1803 let func = &mut *(user_data as *mut F);
1804
1805 let v = mem::replace(
1806 &mut *(value as *mut glib::Value),
1807 glib::Value::uninitialized(),
1808 );
1809 match func(from_glib(quark), v) {
1810 None => glib::ffi::GFALSE,
1811 Some(v) => {
1812 *value = v.into_raw();
1813 glib::ffi::GTRUE
1814 }
1815 }
1816 }
1817 }
1818
1819 let func = &mut func as *mut F;
1820 ffi::gst_structure_filter_and_map_in_place(
1821 self.as_mut_ptr(),
1822 Some(trampoline::<F>),
1823 func as glib::ffi::gpointer,
1824 );
1825 }
1826 }
1827}
1828
1829impl fmt::Display for StructureRef {
1830 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1831 let s = unsafe { glib::GString::from_glib_full(ffi::gst_structure_to_string(&self.0)) };
1832 f.write_str(&s)
1833 }
1834}
1835
1836impl fmt::Debug for StructureRef {
1837 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1838 let mut debug = f.debug_struct(self.name());
1839
1840 for (id, field) in self.iter() {
1841 if field.type_() == Structure::static_type() {
1842 let s = field.get::<Structure>().unwrap();
1843 debug.field(id, &s);
1844 } else if field.type_() == crate::Array::static_type() {
1845 let arr = field.get::<crate::Array>().unwrap();
1846 debug.field(id, &arr);
1847 } else if field.type_() == crate::List::static_type() {
1848 let list = field.get::<crate::List>().unwrap();
1849 debug.field(id, &list);
1850 } else {
1851 debug.field(id, &field);
1852 }
1853 }
1854
1855 debug.finish()
1856 }
1857}
1858
1859impl PartialEq for StructureRef {
1860 #[doc(alias = "gst_structure_is_equal")]
1861 fn eq(&self, other: &StructureRef) -> bool {
1862 unsafe { from_glib(ffi::gst_structure_is_equal(&self.0, &other.0)) }
1863 }
1864}
1865
1866impl Eq for StructureRef {}
1867
1868impl glib::types::StaticType for StructureRef {
1869 #[inline]
1870 fn static_type() -> glib::types::Type {
1871 unsafe { from_glib(ffi::gst_structure_get_type()) }
1872 }
1873}
1874
1875unsafe impl<'a> glib::value::FromValue<'a> for &'a StructureRef {
1876 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
1877
1878 unsafe fn from_value(value: &'a glib::Value) -> Self {
1879 unsafe {
1880 skip_assert_initialized!();
1881 &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const StructureRef)
1882 }
1883 }
1884}
1885
1886impl glib::value::ToValue for StructureRef {
1887 fn to_value(&self) -> glib::Value {
1888 let mut value = glib::Value::for_value_type::<Structure>();
1889 unsafe {
1890 glib::gobject_ffi::g_value_set_boxed(
1891 value.to_glib_none_mut().0,
1892 self.as_ptr() as *mut _,
1893 )
1894 }
1895 value
1896 }
1897
1898 fn value_type(&self) -> glib::Type {
1899 Self::static_type()
1900 }
1901}
1902
1903impl glib::value::ToValueOptional for StructureRef {
1904 fn to_value_optional(s: Option<&Self>) -> glib::Value {
1905 skip_assert_initialized!();
1906 let mut value = glib::Value::for_value_type::<Structure>();
1907 unsafe {
1908 glib::gobject_ffi::g_value_set_boxed(
1909 value.to_glib_none_mut().0,
1910 s.map(|s| s.as_ptr()).unwrap_or(ptr::null()) as *mut _,
1911 )
1912 }
1913 value
1914 }
1915}
1916
1917crate::utils::define_fixed_size_iter!(
1918 FieldIterator,
1919 &'a StructureRef,
1920 &'a glib::GStr,
1921 |collection: &StructureRef| collection.n_fields(),
1922 |collection: &StructureRef, idx: usize| unsafe {
1923 let field_name = ffi::gst_structure_nth_field_name(&collection.0, idx as u32);
1924 glib::GStr::from_ptr(field_name)
1925 }
1926);
1927
1928#[cfg(feature = "v1_26")]
1929crate::utils::define_fixed_size_iter!(
1930 FieldIdIterator,
1931 &'a StructureRef,
1932 &'a crate::IdStr,
1933 |collection: &StructureRef| collection.n_fields(),
1934 |collection: &StructureRef, idx: usize| unsafe {
1935 let field_name = ffi::gst_structure_id_str_nth_field_name(&collection.0, idx as u32);
1936 debug_assert!(!field_name.is_null());
1937
1938 &*(field_name as *const crate::IdStr)
1939 }
1940);
1941
1942#[must_use = "iterators are lazy and do nothing unless consumed"]
1943#[derive(Debug)]
1944pub struct Iter<'a> {
1945 iter: FieldIterator<'a>,
1946}
1947
1948impl<'a> Iter<'a> {
1949 fn new(structure: &'a StructureRef) -> Iter<'a> {
1950 skip_assert_initialized!();
1951 Iter {
1952 iter: FieldIterator::new(structure),
1953 }
1954 }
1955}
1956
1957impl<'a> Iterator for Iter<'a> {
1958 type Item = (&'a glib::GStr, &'a SendValue);
1959
1960 fn next(&mut self) -> Option<Self::Item> {
1961 let f = self.iter.next()?;
1962 let v = self.iter.collection.value(f);
1963 Some((f, v.unwrap()))
1964 }
1965
1966 fn size_hint(&self) -> (usize, Option<usize>) {
1967 self.iter.size_hint()
1968 }
1969
1970 fn count(self) -> usize {
1971 self.iter.count()
1972 }
1973
1974 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1975 let f = self.iter.nth(n)?;
1976 let v = self.iter.collection.value(f);
1977 Some((f, v.unwrap()))
1978 }
1979
1980 fn last(self) -> Option<Self::Item> {
1981 let structure = self.iter.collection;
1982 let f = self.iter.last()?;
1983 let v = structure.value(f);
1984 Some((f, v.unwrap()))
1985 }
1986}
1987
1988impl DoubleEndedIterator for Iter<'_> {
1989 fn next_back(&mut self) -> Option<Self::Item> {
1990 let f = self.iter.next_back()?;
1991 let v = self.iter.collection.value(f);
1992 Some((f, v.unwrap()))
1993 }
1994
1995 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1996 let f = self.iter.nth_back(n)?;
1997 let v = self.iter.collection.value(f);
1998 Some((f, v.unwrap()))
1999 }
2000}
2001
2002impl ExactSizeIterator for Iter<'_> {}
2003
2004impl std::iter::FusedIterator for Iter<'_> {}
2005
2006#[cfg(feature = "v1_26")]
2007#[must_use = "iterators are lazy and do nothing unless consumed"]
2008#[derive(Debug)]
2009pub struct IdIter<'a> {
2010 iter: FieldIdIterator<'a>,
2011}
2012
2013#[cfg(feature = "v1_26")]
2014impl<'a> IdIter<'a> {
2015 fn new(structure: &'a StructureRef) -> IdIter<'a> {
2016 skip_assert_initialized!();
2017 IdIter {
2018 iter: FieldIdIterator::new(structure),
2019 }
2020 }
2021}
2022
2023#[cfg(feature = "v1_26")]
2024impl<'a> Iterator for IdIter<'a> {
2025 type Item = (&'a IdStr, &'a SendValue);
2026
2027 fn next(&mut self) -> Option<Self::Item> {
2028 let f = self.iter.next()?;
2029 let v = self.iter.collection.value_by_id(f);
2030 Some((f, v.unwrap()))
2031 }
2032
2033 fn size_hint(&self) -> (usize, Option<usize>) {
2034 self.iter.size_hint()
2035 }
2036
2037 fn count(self) -> usize {
2038 self.iter.count()
2039 }
2040
2041 fn nth(&mut self, n: usize) -> Option<Self::Item> {
2042 let f = self.iter.nth(n)?;
2043 let v = self.iter.collection.value_by_id(f);
2044 Some((f, v.unwrap()))
2045 }
2046
2047 fn last(self) -> Option<Self::Item> {
2048 let structure = self.iter.collection;
2049 let f = self.iter.last()?;
2050 let v = structure.value_by_id(f);
2051 Some((f, v.unwrap()))
2052 }
2053}
2054
2055#[cfg(feature = "v1_26")]
2056impl DoubleEndedIterator for IdIter<'_> {
2057 fn next_back(&mut self) -> Option<Self::Item> {
2058 let f = self.iter.next_back()?;
2059 let v = self.iter.collection.value_by_id(f);
2060 Some((f, v.unwrap()))
2061 }
2062
2063 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
2064 let f = self.iter.nth_back(n)?;
2065 let v = self.iter.collection.value_by_id(f);
2066 Some((f, v.unwrap()))
2067 }
2068}
2069
2070#[cfg(feature = "v1_26")]
2071impl ExactSizeIterator for IdIter<'_> {}
2072#[cfg(feature = "v1_26")]
2073impl std::iter::FusedIterator for IdIter<'_> {}
2074
2075impl<'a> IntoIterator for &'a StructureRef {
2076 type IntoIter = Iter<'a>;
2077 type Item = (&'a glib::GStr, &'a SendValue);
2078
2079 fn into_iter(self) -> Self::IntoIter {
2080 self.iter()
2081 }
2082}
2083
2084impl<'a> std::iter::Extend<(&'a str, SendValue)> for StructureRef {
2085 fn extend<T: IntoIterator<Item = (&'a str, SendValue)>>(&mut self, iter: T) {
2086 iter.into_iter().for_each(|(f, v)| self.set_value(f, v));
2087 }
2088}
2089
2090impl<'a> std::iter::Extend<(&'a glib::GStr, SendValue)> for StructureRef {
2091 fn extend<T: IntoIterator<Item = (&'a glib::GStr, SendValue)>>(&mut self, iter: T) {
2092 iter.into_iter().for_each(|(f, v)| self.set_value(f, v));
2093 }
2094}
2095
2096impl std::iter::Extend<(String, SendValue)> for StructureRef {
2097 fn extend<T: IntoIterator<Item = (String, SendValue)>>(&mut self, iter: T) {
2098 iter.into_iter().for_each(|(f, v)| self.set_value(&f, v));
2099 }
2100}
2101
2102impl std::iter::Extend<(glib::GString, SendValue)> for StructureRef {
2103 fn extend<T: IntoIterator<Item = (glib::GString, SendValue)>>(&mut self, iter: T) {
2104 iter.into_iter().for_each(|(f, v)| self.set_value(&f, v));
2105 }
2106}
2107
2108impl<'a> std::iter::Extend<(&'a IdStr, SendValue)> for StructureRef {
2109 #[allow(deprecated)]
2110 fn extend<T: IntoIterator<Item = (&'a IdStr, SendValue)>>(&mut self, iter: T) {
2111 iter.into_iter()
2112 .for_each(|(f, v)| self.set_value_with_id(f, v));
2113 }
2114}
2115
2116impl std::iter::Extend<(IdStr, SendValue)> for StructureRef {
2117 #[allow(deprecated)]
2118 fn extend<T: IntoIterator<Item = (IdStr, SendValue)>>(&mut self, iter: T) {
2119 iter.into_iter()
2120 .for_each(|(f, v)| self.set_value_with_id(f, v));
2121 }
2122}
2123
2124impl std::iter::Extend<(glib::Quark, SendValue)> for StructureRef {
2125 #[allow(deprecated)]
2126 fn extend<T: IntoIterator<Item = (glib::Quark, SendValue)>>(&mut self, iter: T) {
2127 iter.into_iter()
2128 .for_each(|(f, v)| self.set_value_by_quark(f, v));
2129 }
2130}
2131
2132#[cfg(feature = "v1_28")]
2134impl std::hash::Hash for StructureRef {
2135 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2136 use crate::value::GstValueExt;
2137 use std::hash::{DefaultHasher, Hasher};
2138
2139 let name = self.name();
2140 name.hash(state);
2141
2142 let mut fields_hash = 0;
2144 for (field, value) in self.iter() {
2145 let mut field_hasher = DefaultHasher::new();
2146 field.hash(&mut field_hasher);
2147 let value_hash = value.hash().unwrap();
2148 value_hash.hash(&mut field_hasher);
2149
2150 fields_hash ^= field_hasher.finish();
2151 }
2152 fields_hash.hash(state);
2153 }
2154}
2155
2156#[cfg(feature = "v1_28")]
2157impl std::hash::Hash for Structure {
2158 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2159 self.as_ref().hash(state);
2160 }
2161}
2162
2163#[derive(Debug)]
2164#[must_use = "The builder must be built to be used"]
2165pub struct Builder {
2166 s: Structure,
2167}
2168
2169impl Builder {
2170 fn new(name: impl IntoGStr) -> Self {
2171 skip_assert_initialized!();
2172 Builder {
2173 s: Structure::new_empty(name),
2174 }
2175 }
2176
2177 fn from_static(name: impl AsRef<GStr> + 'static) -> Self {
2178 skip_assert_initialized!();
2179 Builder {
2180 s: Structure::new_empty_from_static(name),
2181 }
2182 }
2183
2184 pub fn from_id(name: impl AsRef<IdStr>) -> Builder {
2185 skip_assert_initialized!();
2186 Builder {
2187 s: Structure::new_empty_from_id(name),
2188 }
2189 }
2190
2191 #[inline]
2196 pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self {
2197 self.s.set(name, value);
2198 self
2199 }
2200
2201 #[inline]
2206 pub fn field_with_static(
2207 mut self,
2208 name: impl AsRef<GStr> + 'static,
2209 value: impl Into<glib::Value> + Send,
2210 ) -> Self {
2211 self.s.set_with_static(name, value);
2212 self
2213 }
2214
2215 #[inline]
2220 pub fn field_with_id(
2221 mut self,
2222 name: impl AsRef<IdStr>,
2223 value: impl Into<glib::Value> + Send,
2224 ) -> Self {
2225 self.s.set_with_id(name, value);
2226 self
2227 }
2228
2229 impl_builder_gvalue_extra_setters!(field);
2230
2231 #[must_use = "Building the structure without using it has no effect"]
2232 pub fn build(self) -> Structure {
2233 self.s
2234 }
2235}
2236
2237#[cfg(test)]
2238mod tests {
2239 use super::*;
2240 use glib::gstr;
2241
2242 #[test]
2243 fn new_set_get() {
2244 use glib::{Type, value};
2245
2246 crate::init().unwrap();
2247
2248 let mut s = Structure::new_empty("test");
2249 assert_eq!(s.name(), "test");
2250
2251 s.set("f1", "abc");
2252 s.set("f2", String::from("bcd"));
2253 s.set("f3", 123i32);
2254 s.set("f5", Some("efg"));
2255 s.set("f7", 42i32);
2256
2257 assert_eq!(s.get::<&str>("f1"), Ok("abc"));
2258 assert_eq!(s.get::<Option<&str>>("f2"), Ok(Some("bcd")));
2259 assert_eq!(s.get::<i32>("f3"), Ok(123i32));
2260 assert_eq!(s.get_optional::<&str>("f1"), Ok(Some("abc")));
2261 assert_eq!(s.get_optional::<&str>("f4"), Ok(None));
2262 assert_eq!(s.get_optional::<i32>("f3"), Ok(Some(123i32)));
2263 assert_eq!(s.get_optional::<i32>("f4"), Ok(None));
2264 assert_eq!(s.get::<&str>("f5"), Ok("efg"));
2265 assert_eq!(s.get::<i32>("f7"), Ok(42i32));
2266
2267 assert_eq!(
2268 s.get::<i32>("f2"),
2269 Err(GetError::from_value_get_error(
2270 idstr!("f2"),
2271 value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
2272 ))
2273 );
2274 assert_eq!(
2275 s.get::<bool>("f3"),
2276 Err(GetError::from_value_get_error(
2277 idstr!("f3"),
2278 value::ValueTypeMismatchError::new(Type::I32, Type::BOOL),
2279 ))
2280 );
2281 assert_eq!(
2282 s.get::<&str>("f4"),
2283 Err(GetError::new_field_not_found(idstr!("f4")))
2284 );
2285 assert_eq!(
2286 s.get::<i32>("f4"),
2287 Err(GetError::new_field_not_found(idstr!("f4")))
2288 );
2289
2290 assert_eq!(
2291 s.fields().collect::<Vec<_>>(),
2292 vec!["f1", "f2", "f3", "f5", "f7"]
2293 );
2294
2295 let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>();
2296 assert_eq!(v.len(), 5);
2297 assert_eq!(v[0].0, "f1");
2298 assert_eq!(v[0].1.get::<&str>(), Ok("abc"));
2299 assert_eq!(v[1].0, "f2");
2300 assert_eq!(v[1].1.get::<&str>(), Ok("bcd"));
2301 assert_eq!(v[2].0, "f3");
2302 assert_eq!(v[2].1.get::<i32>(), Ok(123i32));
2303 assert_eq!(v[3].0, "f5");
2304 assert_eq!(v[3].1.get::<&str>(), Ok("efg"));
2305 assert_eq!(v[4].0, "f7");
2306 assert_eq!(v[4].1.get::<i32>(), Ok(42i32));
2307
2308 let s2 = Structure::builder("test")
2309 .field("f1", "abc")
2310 .field("f2", String::from("bcd"))
2311 .field("f3", 123i32)
2312 .field_if_some("f4", Option::<i32>::None)
2313 .field_if_some("f5", Some("efg"))
2314 .field_if_some("f6", Option::<&str>::None)
2315 .field_if("f7", 42i32, true)
2316 .field_if("f8", 21i32, false)
2317 .build();
2318 assert_eq!(s, s2);
2319
2320 let mut s3 = Structure::new_empty("test");
2321
2322 s3.set_if_some("f1", Some("abc"));
2323 s3.set_if_some("f2", Some(String::from("bcd")));
2324 s3.set_if_some("f3", Some(123i32));
2325 s3.set_if_some("f4", Option::<i32>::None);
2326 s3.set_if_some("f5", Some("efg"));
2327 s3.set_if_some("f6", Option::<&str>::None);
2328 s3.set_if("f7", 42i32, true);
2329 s3.set_if("f8", 21i32, false);
2330 assert_eq!(s, s3);
2331 }
2332
2333 #[test]
2334 fn new_set_get_static() {
2335 use glib::{Type, value};
2336
2337 crate::init().unwrap();
2338
2339 let mut s = Structure::new_empty_from_static(gstr!("test"));
2340 assert_eq!(s.name(), "test");
2341
2342 static F1: &GStr = gstr!("f1");
2343 static F2: &GStr = gstr!("f2");
2344 static F3: &GStr = gstr!("f3");
2345
2346 s.set_with_static(F1, "abc");
2347 s.set_with_static_if(F2, String::from("bcd"), true);
2348 s.set_with_static_if(F3, "not_set", false);
2349
2350 assert_eq!(s.get::<&str>(F1), Ok("abc"));
2351 assert_eq!(s.get::<Option<&str>>(F2), Ok(Some("bcd")));
2352 assert_eq!(s.get_optional::<&str>(F1), Ok(Some("abc")));
2353 assert_eq!(s.get_optional::<&str>(F3), Ok(None));
2354
2355 assert_eq!(
2356 s.get::<i32>(F2),
2357 Err(GetError::from_value_get_error(
2358 idstr!("f2"),
2359 value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
2360 ))
2361 );
2362 assert_eq!(
2363 s.get::<&str>(F3),
2364 Err(GetError::new_field_not_found(idstr!("f3")))
2365 );
2366
2367 let s2 = Structure::builder("test")
2368 .field_with_static(F1, "abc")
2369 .field_with_static(F2, String::from("bcd"))
2370 .build();
2371 assert_eq!(s, s2);
2372
2373 let mut s3 = Structure::new_empty("test");
2374
2375 s3.set_with_static_if_some(F1, Some("abc"));
2376 s3.set_with_static_if_some(F2, Some(String::from("bcd")));
2377
2378 assert_eq!(s, s3);
2379 }
2380
2381 #[test]
2382 fn new_set_get_id_str() {
2383 use glib::{Type, value};
2384
2385 crate::init().unwrap();
2386
2387 let mut s = Structure::new_empty_from_id(idstr!("test"));
2388 assert_eq!(s.name(), "test");
2389 #[cfg(feature = "v1_26")]
2390 assert_eq!(s.name_id(), "test");
2391
2392 let f1 = idstr!("f1");
2393 let f2 = idstr!("f2");
2394 let f3 = idstr!("f3");
2395
2396 s.set_with_id(&f1, "abc");
2397 s.set_with_id_if(&f2, String::from("bcd"), true);
2398 s.set_with_id_if(&f3, "not_set", false);
2399
2400 assert_eq!(s.get_by_id::<&str>(&f1), Ok("abc"));
2401 assert_eq!(s.get_by_id::<&str>(f1.clone()), Ok("abc"));
2402 assert_eq!(s.get_by_id::<Option<&str>>(&f2), Ok(Some("bcd")));
2403 assert_eq!(s.get_by_id::<Option<&str>>(f2.clone()), Ok(Some("bcd")));
2404 assert_eq!(s.get_optional_by_id::<&str>(&f1), Ok(Some("abc")));
2405 assert_eq!(s.get_optional_by_id::<&str>(&f3), Ok(None));
2406
2407 assert_eq!(
2408 s.get_by_id::<i32>(&f2),
2409 Err(GetError::from_value_get_error(
2410 f2.clone(),
2411 value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
2412 ))
2413 );
2414 assert_eq!(
2415 s.get_by_id::<&str>(&f3),
2416 Err(GetError::new_field_not_found(f3.clone()))
2417 );
2418
2419 let s2 = Structure::builder("test")
2420 .field_with_id(&f1, "abc")
2421 .field_with_id(&f2, String::from("bcd"))
2422 .build();
2423 assert_eq!(s, s2);
2424
2425 let mut s3 = Structure::new_empty("test");
2426
2427 s3.set_with_id_if_some(f1, Some("abc"));
2428 s3.set_with_id_if_some(f2, Some(String::from("bcd")));
2429
2430 assert_eq!(s, s3);
2431 }
2432
2433 #[test]
2434 fn test_string_conversion() {
2435 crate::init().unwrap();
2436
2437 let a = "Test, f1=(string)abc, f2=(uint)123;";
2438
2439 let s = a.parse::<Structure>().unwrap();
2440 assert_eq!(s.get::<&str>("f1"), Ok("abc"));
2441 assert_eq!(s.get::<u32>("f2"), Ok(123));
2442
2443 assert_eq!(a, s.to_string());
2444 }
2445
2446 #[test]
2447 fn test_from_value_optional() {
2448 use glib::value::ToValue;
2449
2450 crate::init().unwrap();
2451
2452 let a = None::<&Structure>.to_value();
2453 assert!(a.get::<Option<Structure>>().unwrap().is_none());
2454 let b = "foo".parse::<Structure>().unwrap().to_value();
2455 assert!(b.get::<Option<Structure>>().unwrap().is_some());
2456 }
2457
2458 #[test]
2459 fn test_new_from_iter() {
2460 crate::init().unwrap();
2461
2462 let s = Structure::builder("test")
2463 .field("f1", "abc")
2464 .field_with_static(gstr!("f2"), String::from("bcd"))
2465 .field_with_id(idstr!("f3"), 123i32)
2466 .build();
2467
2468 let s2 = Structure::from_iter(
2469 s.name(),
2470 s.iter()
2471 .filter(|(f, _)| *f == "f1")
2472 .map(|(f, v)| (f, v.clone())),
2473 );
2474
2475 assert_eq!(s2.name(), "test");
2476 assert_eq!(s2.get::<&str>("f1"), Ok("abc"));
2477 assert!(s2.get::<&str>("f2").is_err());
2478 assert!(s2.get_by_id::<&str>(idstr!("f3")).is_err());
2479 }
2480
2481 #[test]
2482 fn test_debug() {
2483 crate::init().unwrap();
2484
2485 let s = Structure::builder("test")
2486 .field("f1", "abc")
2487 .field("f2", String::from("bcd"))
2488 .field("f3", 123i32)
2489 .field(
2490 "f4",
2491 Structure::builder("nested").field("badger", true).build(),
2492 )
2493 .field("f5", crate::Array::new(["a", "b", "c"]))
2494 .field("f6", crate::List::new(["d", "e", "f"]))
2495 .build();
2496
2497 assert_eq!(
2498 format!("{s:?}"),
2499 "Structure(test { f1: (gchararray) \"abc\", f2: (gchararray) \"bcd\", f3: (gint) 123, f4: Structure(nested { badger: (gboolean) TRUE }), f5: Array([(gchararray) \"a\", (gchararray) \"b\", (gchararray) \"c\"]), f6: List([(gchararray) \"d\", (gchararray) \"e\", (gchararray) \"f\"]) })"
2500 );
2501 }
2502
2503 #[test]
2504 fn builder_field_from_iter() {
2505 crate::init().unwrap();
2506
2507 static SLIST: &GStr = gstr!("slist");
2508 let ilist = idstr!("ilist");
2509 let s = Structure::builder("test")
2510 .field_from_iter::<crate::Array, i32>("array", [1, 2, 3])
2511 .field_with_static_from_iter::<crate::List, i32>(SLIST, [4, 5, 6])
2512 .field_with_id_from_iter::<crate::List, i32>(&ilist, [7, 8, 9])
2513 .build();
2514 assert!(
2515 s.get::<crate::Array>("array")
2516 .unwrap()
2517 .iter()
2518 .map(|val| val.get::<i32>().unwrap())
2519 .eq([1, 2, 3])
2520 );
2521 assert!(
2522 s.get::<crate::List>("slist")
2523 .unwrap()
2524 .iter()
2525 .map(|val| val.get::<i32>().unwrap())
2526 .eq([4, 5, 6])
2527 );
2528 assert!(
2529 s.get_by_id::<crate::List>(&ilist)
2530 .unwrap()
2531 .iter()
2532 .map(|val| val.get::<i32>().unwrap())
2533 .eq([7, 8, 9])
2534 );
2535
2536 let array = Vec::<i32>::new();
2537 let s = Structure::builder("test")
2538 .field_from_iter::<crate::Array, _>("array", &array)
2539 .field_with_static_from_iter::<crate::List, _>(SLIST, &array)
2540 .field_with_id_from_iter::<crate::List, _>(&ilist, &array)
2541 .build();
2542 assert!(s.get::<crate::Array>("array").unwrap().as_ref().is_empty());
2543 assert!(s.get::<crate::List>(SLIST).unwrap().as_ref().is_empty());
2544 assert!(
2545 s.get_by_id::<crate::List>(ilist)
2546 .unwrap()
2547 .as_ref()
2548 .is_empty()
2549 );
2550 }
2551
2552 #[test]
2553 fn builder_field_if_not_empty() {
2554 crate::init().unwrap();
2555
2556 static SLIST: &GStr = gstr!("slist");
2557 let ilist = idstr!("ilist");
2558 let s = Structure::builder_from_id(idstr!("test"))
2559 .field_if_not_empty::<crate::Array, i32>("array", [1, 2, 3])
2560 .field_with_static_if_not_empty::<crate::List, i32>(SLIST, [4, 5, 6])
2561 .field_with_id_if_not_empty::<crate::List, i32>(&ilist, [7, 8, 9])
2562 .build();
2563 assert!(
2564 s.get::<crate::Array>("array")
2565 .unwrap()
2566 .iter()
2567 .map(|val| val.get::<i32>().unwrap())
2568 .eq([1, 2, 3])
2569 );
2570 assert!(
2571 s.get::<crate::List>("slist")
2572 .unwrap()
2573 .iter()
2574 .map(|val| val.get::<i32>().unwrap())
2575 .eq([4, 5, 6])
2576 );
2577 assert!(
2578 s.get_by_id::<crate::List>(&ilist)
2579 .unwrap()
2580 .iter()
2581 .map(|val| val.get::<i32>().unwrap())
2582 .eq([7, 8, 9])
2583 );
2584
2585 let array = Vec::<i32>::new();
2586 let s = Structure::builder("test")
2587 .field_if_not_empty::<crate::Array, _>("array", &array)
2588 .field_with_static_if_not_empty::<crate::List, _>(SLIST, &array)
2589 .field_with_id_if_not_empty::<crate::List, _>(ilist, &array)
2590 .build();
2591 assert!(!s.has_field("array"));
2592 assert!(!s.has_field("slist"));
2593 assert!(!s.has_field("ilist"));
2594 }
2595
2596 #[test]
2597 fn nth_field_remove_field() {
2598 crate::init().unwrap();
2599
2600 let f3 = idstr!("f3");
2601 let f5 = idstr!("f5");
2602 let f8 = idstr!("f8");
2603 let mut s = Structure::builder("test")
2604 .field("f1", "abc")
2605 .field("f2", "bcd")
2606 .field_with_id(&f3, "cde")
2607 .field("f4", "def")
2608 .field_with_id(&f5, "efg")
2609 .field("f6", "fgh")
2610 .field("f7", "ghi")
2611 .field_with_id(&f8, "hij")
2612 .build();
2613
2614 assert_eq!(s.iter().next().unwrap().0, "f1");
2615 assert_eq!(
2616 s.fields().collect::<Vec<_>>(),
2617 vec!["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"]
2618 );
2619 assert!(s.has_field("f8"));
2620 assert_eq!(s.nth_field_name(7), Some(gstr!("f8")));
2621 assert!(s.nth_field_name(8).is_none());
2622
2623 #[cfg(feature = "v1_26")]
2624 assert_eq!(s.id_iter().next().unwrap().0, "f1");
2625 #[cfg(feature = "v1_26")]
2626 assert_eq!(
2627 s.field_ids().collect::<Vec<_>>(),
2628 vec!["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"]
2629 );
2630 #[cfg(feature = "v1_26")]
2631 assert!(s.has_field_by_id(&f8));
2632 #[cfg(feature = "v1_26")]
2633 assert_eq!(s.nth_field_by_id(7), Some(&f8));
2634 #[cfg(feature = "v1_26")]
2635 assert!(s.nth_field_by_id(8).is_none());
2636
2637 assert_eq!(s.nth_field_name(1), Some(gstr!("f2")));
2638 s.remove_field("f2");
2639 assert_eq!(s.nth_field_name(1), Some(gstr!("f3")));
2640 assert!(s.nth_field_name(7).is_none());
2641 assert_eq!(
2642 s.fields().collect::<Vec<_>>(),
2643 vec!["f1", "f3", "f4", "f5", "f6", "f7", "f8"]
2644 );
2645
2646 assert_eq!(s.nth_field_name(1), Some(gstr!("f3")));
2647 s.remove_field_by_id(&f3);
2648 assert_eq!(s.nth_field_name(1), Some(gstr!("f4")));
2649 assert!(s.nth_field_name(6).is_none());
2650 #[cfg(feature = "v1_26")]
2651 assert_eq!(s.nth_field_by_id(2), Some(&f5));
2652 #[cfg(feature = "v1_26")]
2653 assert!(s.nth_field_by_id(6).is_none());
2654 assert_eq!(
2655 s.fields().collect::<Vec<_>>(),
2656 vec!["f1", "f4", "f5", "f6", "f7", "f8"]
2657 );
2658
2659 s.remove_fields(["f4", "f6"]);
2660 assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f5", "f7", "f8"]);
2661
2662 s.remove_field_by_ids([&f5, &f8]);
2663 assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f7"]);
2664 #[cfg(feature = "v1_26")]
2665 assert_eq!(s.field_ids().collect::<Vec<_>>(), vec!["f1", "f7"]);
2666
2667 s.remove_all_fields();
2668 assert!(s.is_empty());
2669 }
2670
2671 #[cfg(feature = "v1_26")]
2672 #[test]
2673 fn map_in_place() {
2674 crate::init().unwrap();
2675
2676 let f1 = idstr!("f1");
2677 let f2 = idstr!("f2");
2678 let f3 = idstr!("f3");
2679 let mut s = Structure::builder_from_id(idstr!("test"))
2680 .field_with_id(&f1, "abc")
2681 .field_with_id(&f2, "bcd")
2682 .field_with_id(&f3, false)
2683 .build();
2684 assert!(!s.get_by_id::<bool>(&f3).unwrap());
2685
2686 s.map_in_place_by_id(|name, value| {
2687 if *name == f3 {
2688 *value = true.into()
2689 }
2690
2691 std::ops::ControlFlow::Continue(())
2692 });
2693 assert!(s.get_by_id::<bool>(&f3).unwrap());
2694
2695 s.map_in_place_by_id(|name, value| {
2696 match name.as_str() {
2697 "f2" => return std::ops::ControlFlow::Break(()),
2698 "f3" => *value = false.into(),
2699 _ => (),
2700 }
2701 std::ops::ControlFlow::Continue(())
2702 });
2703 assert!(s.get_by_id::<bool>(&f3).unwrap());
2704
2705 s.filter_map_in_place_by_id(|name, value| {
2706 if *name == f3 && value.get::<bool>().unwrap() {
2707 None
2708 } else {
2709 Some(value)
2710 }
2711 });
2712
2713 assert_eq!(s.field_ids().collect::<Vec<_>>(), vec![&f1, &f2]);
2714 }
2715
2716 #[cfg(feature = "v1_28")]
2717 #[test]
2718 fn test_hash() {
2719 crate::init().unwrap();
2720
2721 use std::hash::BuildHasher;
2722 let bh = std::hash::RandomState::new();
2723
2724 let s1 = Structure::builder("test1").build();
2726 let s2 = Structure::builder("test2").build();
2727 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s1));
2728 assert_eq!(bh.hash_one(&s2), bh.hash_one(&s2));
2729 assert_ne!(bh.hash_one(&s1), bh.hash_one(&s2));
2730
2731 let s1 = Structure::builder("test").field("a", 1u32).build();
2733 let s2 = Structure::builder("test").field("b", 1u32).build();
2734 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s1));
2735 assert_eq!(bh.hash_one(&s2), bh.hash_one(&s2));
2736 assert_ne!(bh.hash_one(&s1), bh.hash_one(&s2));
2737
2738 let s1 = Structure::builder("test").field("a", 1u32).build();
2740 let s2 = Structure::builder("test").field("a", 2u32).build();
2741 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s1));
2742 assert_eq!(bh.hash_one(&s2), bh.hash_one(&s2));
2743 assert_ne!(bh.hash_one(&s1), bh.hash_one(&s2));
2744
2745 let s1 = Structure::builder("test")
2747 .field("a", 1u32)
2748 .field("b", 2u32)
2749 .build();
2750 let s2 = Structure::builder("test")
2751 .field("b", 2u32)
2752 .field("a", 1u32)
2753 .build();
2754 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s1));
2755 assert_eq!(bh.hash_one(&s2), bh.hash_one(&s2));
2756 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s2));
2757 }
2758}