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 prelude::*,
15 translate::*,
16 value::{FromValue, SendValue, Value},
17 GStr, IntoGStr,
18};
19
20use crate::{ffi, Fraction, IdStr};
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 debug_assert!(!ptr.is_null());
470 let ptr = ffi::gst_structure_copy(ptr);
471 debug_assert!(!ptr.is_null());
472 Structure(ptr::NonNull::new_unchecked(ptr))
473 }
474}
475
476impl FromGlibPtrNone<*mut ffi::GstStructure> for Structure {
477 #[inline]
478 unsafe fn from_glib_none(ptr: *mut ffi::GstStructure) -> Self {
479 debug_assert!(!ptr.is_null());
480 let ptr = ffi::gst_structure_copy(ptr);
481 debug_assert!(!ptr.is_null());
482 Structure(ptr::NonNull::new_unchecked(ptr))
483 }
484}
485
486impl FromGlibPtrFull<*const ffi::GstStructure> for Structure {
487 #[inline]
488 unsafe fn from_glib_full(ptr: *const ffi::GstStructure) -> Self {
489 debug_assert!(!ptr.is_null());
490 Structure(ptr::NonNull::new_unchecked(ptr as *mut ffi::GstStructure))
491 }
492}
493
494impl FromGlibPtrFull<*mut ffi::GstStructure> for Structure {
495 #[inline]
496 unsafe fn from_glib_full(ptr: *mut ffi::GstStructure) -> Self {
497 debug_assert!(!ptr.is_null());
498 Structure(ptr::NonNull::new_unchecked(ptr))
499 }
500}
501
502impl FromGlibPtrBorrow<*const ffi::GstStructure> for Structure {
503 #[inline]
504 unsafe fn from_glib_borrow(ptr: *const ffi::GstStructure) -> Borrowed<Self> {
505 Borrowed::new(from_glib_full(ptr))
506 }
507}
508
509impl FromGlibPtrBorrow<*mut ffi::GstStructure> for Structure {
510 #[inline]
511 unsafe fn from_glib_borrow(ptr: *mut ffi::GstStructure) -> Borrowed<Self> {
512 Borrowed::new(from_glib_full(ptr))
513 }
514}
515
516impl glib::value::ValueType for Structure {
517 type Type = Self;
518}
519
520impl glib::value::ValueTypeOptional for Structure {}
521
522unsafe impl<'a> glib::value::FromValue<'a> for Structure {
523 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
524
525 unsafe fn from_value(value: &'a glib::Value) -> Self {
526 skip_assert_initialized!();
527 from_glib_none(
528 glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstStructure
529 )
530 }
531}
532
533impl glib::value::ToValue for Structure {
534 fn to_value(&self) -> glib::Value {
535 let mut value = glib::Value::for_value_type::<Self>();
536 unsafe {
537 glib::gobject_ffi::g_value_set_boxed(
538 value.to_glib_none_mut().0,
539 glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(self).0
540 as *mut _,
541 )
542 }
543 value
544 }
545
546 fn value_type(&self) -> glib::Type {
547 Self::static_type()
548 }
549}
550
551impl glib::value::ToValueOptional for Structure {
552 fn to_value_optional(s: Option<&Self>) -> glib::Value {
553 skip_assert_initialized!();
554 let mut value = glib::Value::for_value_type::<Self>();
555 unsafe {
556 glib::gobject_ffi::g_value_set_boxed(
557 value.to_glib_none_mut().0,
558 glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(&s).0
559 as *mut _,
560 )
561 }
562 value
563 }
564}
565
566impl From<Structure> for glib::Value {
567 fn from(v: Structure) -> glib::Value {
568 skip_assert_initialized!();
569 let mut value = glib::Value::for_value_type::<Structure>();
570 unsafe {
571 glib::gobject_ffi::g_value_take_boxed(
572 value.to_glib_none_mut().0,
573 glib::translate::IntoGlibPtr::<*mut ffi::GstStructure>::into_glib_ptr(v) as *mut _,
574 )
575 }
576 value
577 }
578}
579
580impl GlibPtrDefault for Structure {
581 type GlibType = *mut ffi::GstStructure;
582}
583
584unsafe impl TransparentPtrType for Structure {}
585
586#[repr(transparent)]
587#[doc(alias = "GstStructure")]
588pub struct StructureRef(ffi::GstStructure);
589
590unsafe impl Send for StructureRef {}
591unsafe impl Sync for StructureRef {}
592
593impl StructureRef {
594 #[inline]
595 pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstStructure) -> &'a StructureRef {
596 debug_assert!(!ptr.is_null());
597
598 &*(ptr as *mut StructureRef)
599 }
600
601 #[inline]
602 pub unsafe fn from_glib_borrow_mut<'a>(ptr: *mut ffi::GstStructure) -> &'a mut StructureRef {
603 debug_assert!(!ptr.is_null());
604 #[cfg(feature = "v1_28")]
605 debug_assert_ne!(ffi::gst_structure_is_writable(ptr), glib::ffi::GFALSE,);
606
607 &mut *(ptr as *mut StructureRef)
608 }
609
610 #[inline]
611 pub fn as_ptr(&self) -> *const ffi::GstStructure {
612 self as *const Self as *const ffi::GstStructure
613 }
614
615 #[inline]
616 pub fn as_mut_ptr(&self) -> *mut ffi::GstStructure {
617 self as *const Self as *mut ffi::GstStructure
618 }
619
620 #[doc(alias = "gst_structure_get")]
621 pub fn get<'a, T: FromValue<'a>>(
622 &'a self,
623 name: impl IntoGStr,
624 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
625 {
626 name.run_with_gstr(|name| {
627 self.value(name)
628 .map_err(|err| match err {
629 GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
630 _ => unreachable!(),
631 })?
632 .get()
633 .map_err(|err| GetError::from_value_get_error(IdStr::from(name), err))
634 })
635 }
636
637 #[doc(alias = "gst_structure_id_str_get")]
638 #[inline]
639 pub fn get_by_id<'a, T: FromValue<'a>>(
640 &'a self,
641 name: impl AsRef<IdStr>,
642 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
643 {
644 self.value_by_id(name.as_ref())
645 .map_err(|err| match err {
646 GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
647 _ => unreachable!(),
648 })?
649 .get()
650 .map_err(|err| GetError::from_value_get_error(name, err))
651 }
652
653 #[doc(alias = "gst_structure_get")]
654 pub fn get_optional<'a, T: FromValue<'a>>(
655 &'a self,
656 name: impl IntoGStr,
657 ) -> Result<
658 Option<T>,
659 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
660 > {
661 name.run_with_gstr(|name| {
662 self.value(name)
663 .ok()
664 .map(|v| v.get())
665 .transpose()
666 .map_err(|err| GetError::from_value_get_error(IdStr::from(name), err))
667 })
668 }
669
670 #[doc(alias = "gst_structure_id_str_get")]
671 pub fn get_optional_by_id<'a, T: FromValue<'a>>(
672 &'a self,
673 name: impl AsRef<IdStr>,
674 ) -> Result<
675 Option<T>,
676 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
677 > {
678 self.value_by_id(name.as_ref())
679 .ok()
680 .map(|v| v.get())
681 .transpose()
682 .map_err(|err| GetError::from_value_get_error(name, err))
683 }
684
685 #[doc(alias = "get_value")]
686 #[doc(alias = "gst_structure_get_value")]
687 pub fn value(
688 &self,
689 name: impl IntoGStr,
690 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
691 unsafe {
692 name.run_with_gstr(|name| {
693 let value = ffi::gst_structure_get_value(&self.0, name.as_ptr());
694
695 if value.is_null() {
696 return Err(GetError::new_field_not_found(IdStr::from(name)));
697 }
698
699 Ok(&*(value as *const SendValue))
700 })
701 }
702 }
703
704 #[doc(alias = "gst_structure_id_str_get_value")]
705 pub fn value_by_id(
706 &self,
707 name: impl AsRef<IdStr>,
708 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
709 unsafe {
710 cfg_if! {
711 if #[cfg(feature = "v1_26")] {
712 let value = ffi::gst_structure_id_str_get_value(&self.0, name.as_ref().as_ptr());
713 } else {
714 let value = ffi::gst_structure_get_value(&self.0, name.as_ref().as_gstr().as_ptr());
715 }
716 }
717
718 if value.is_null() {
719 return Err(GetError::new_field_not_found(name));
720 }
721
722 Ok(&*(value as *const SendValue))
723 }
724 }
725
726 #[deprecated = "use `get_by_id()` instead"]
727 #[allow(deprecated)]
728 #[doc(alias = "gst_structure_id_get")]
729 pub fn get_by_quark<'a, T: FromValue<'a>>(
730 &'a self,
731 name: glib::Quark,
732 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
733 {
734 self.value_by_quark(name)
735 .map_err(|err| match err {
736 GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
737 _ => unreachable!(),
738 })?
739 .get()
740 .map_err(|err| GetError::from_value_get_error(IdStr::from(name.as_str()), err))
741 }
742
743 #[deprecated = "use `get_optional_by_id()` instead"]
744 #[allow(deprecated)]
745 #[doc(alias = "gst_structure_id_get")]
746 pub fn get_optional_by_quark<'a, T: FromValue<'a>>(
747 &'a self,
748 name: glib::Quark,
749 ) -> Result<
750 Option<T>,
751 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
752 > {
753 self.value_by_quark(name)
754 .ok()
755 .map(|v| v.get())
756 .transpose()
757 .map_err(|err| GetError::from_value_get_error(IdStr::from(name.as_str()), err))
758 }
759
760 #[deprecated = "use `value_by_id()` instead"]
761 #[doc(alias = "gst_structure_id_get_value")]
762 pub fn value_by_quark(
763 &self,
764 name: glib::Quark,
765 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
766 unsafe {
767 let value = ffi::gst_structure_id_get_value(&self.0, name.into_glib());
768
769 if value.is_null() {
770 return Err(GetError::new_field_not_found(IdStr::from(name.as_str())));
771 }
772
773 Ok(&*(value as *const SendValue))
774 }
775 }
776
777 #[doc(alias = "gst_structure_set")]
782 pub fn set(&mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) {
783 let value = glib::SendValue::from_owned(value);
784 self.set_value(name, value);
785 }
786
787 #[doc(alias = "gst_structure_set_static_str")]
792 pub fn set_with_static(
793 &mut self,
794 name: impl AsRef<GStr> + 'static,
795 value: impl Into<glib::Value> + Send,
796 ) {
797 let value = glib::SendValue::from_owned(value);
798 self.set_value_with_static(name, value);
799 }
800
801 #[doc(alias = "gst_structure_id_str_set")]
806 pub fn set_with_id(&mut self, name: impl AsRef<IdStr>, value: impl Into<glib::Value> + Send) {
807 let value = glib::SendValue::from_owned(value);
808 self.set_value_with_id(name, value);
809 }
810
811 #[doc(alias = "gst_structure_set")]
817 pub fn set_if(
818 &mut self,
819 name: impl IntoGStr,
820 value: impl Into<glib::Value> + Send,
821 predicate: bool,
822 ) {
823 if predicate {
824 self.set(name, value);
825 }
826 }
827
828 #[doc(alias = "gst_structure_set_static_str")]
834 pub fn set_with_static_if(
835 &mut self,
836 name: impl AsRef<GStr> + 'static,
837 value: impl Into<glib::Value> + Send,
838 predicate: bool,
839 ) {
840 if predicate {
841 self.set_with_static(name, value);
842 }
843 }
844
845 #[doc(alias = "gst_structure_id_str_set")]
851 pub fn set_with_id_if(
852 &mut self,
853 name: impl AsRef<IdStr>,
854 value: impl Into<glib::Value> + Send,
855 predicate: bool,
856 ) {
857 if predicate {
858 self.set_with_id(name, value);
859 }
860 }
861
862 #[doc(alias = "gst_structure_set")]
867 pub fn set_if_some(
868 &mut self,
869 name: impl IntoGStr,
870 value: Option<impl Into<glib::Value> + Send>,
871 ) {
872 if let Some(value) = value {
873 self.set(name, value);
874 }
875 }
876
877 #[doc(alias = "gst_structure_set_static_str")]
882 pub fn set_with_static_if_some(
883 &mut self,
884 name: impl AsRef<GStr> + 'static,
885 value: Option<impl Into<glib::Value> + Send>,
886 ) {
887 if let Some(value) = value {
888 self.set_with_static(name, value);
889 }
890 }
891
892 #[doc(alias = "gst_structure_id_str_set")]
897 pub fn set_with_id_if_some(
898 &mut self,
899 name: impl AsRef<IdStr>,
900 value: Option<impl Into<glib::Value> + Send>,
901 ) {
902 if let Some(value) = value {
903 self.set_with_id(name, value);
904 }
905 }
906
907 #[inline]
912 pub fn set_from_iter<
913 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
914 I: ToSendValue,
915 >(
916 &mut self,
917 name: impl IntoGStr,
918 iter: impl IntoIterator<Item = I>,
919 ) {
920 let iter = iter.into_iter().map(|item| item.to_send_value());
921 self.set(name, V::from_iter(iter));
922 }
923
924 #[inline]
929 pub fn set_with_static_from_iter<
930 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
931 I: ToSendValue,
932 >(
933 &mut self,
934 name: impl AsRef<GStr> + 'static,
935 iter: impl IntoIterator<Item = I>,
936 ) {
937 let iter = iter.into_iter().map(|item| item.to_send_value());
938 self.set_with_static(name, V::from_iter(iter));
939 }
940
941 #[inline]
946 pub fn set_with_id_from_iter<
947 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
948 I: ToSendValue,
949 >(
950 &mut self,
951 name: impl AsRef<IdStr>,
952 iter: impl IntoIterator<Item = I>,
953 ) {
954 let iter = iter.into_iter().map(|item| item.to_send_value());
955 self.set_with_id(name, V::from_iter(iter));
956 }
957
958 #[inline]
964 pub fn set_if_not_empty<
965 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
966 I: ToSendValue,
967 >(
968 &mut self,
969 name: impl IntoGStr,
970 iter: impl IntoIterator<Item = I>,
971 ) {
972 let mut iter = iter.into_iter().peekable();
973 if iter.peek().is_some() {
974 let iter = iter.map(|item| item.to_send_value());
975 self.set(name, V::from_iter(iter));
976 }
977 }
978
979 #[inline]
985 pub fn set_with_static_if_not_empty<
986 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
987 I: ToSendValue,
988 >(
989 &mut self,
990 name: impl AsRef<GStr> + 'static,
991 iter: impl IntoIterator<Item = I>,
992 ) {
993 let mut iter = iter.into_iter().peekable();
994 if iter.peek().is_some() {
995 let iter = iter.map(|item| item.to_send_value());
996 self.set_with_static(name, V::from_iter(iter));
997 }
998 }
999
1000 #[inline]
1006 pub fn set_with_id_if_not_empty<
1007 V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
1008 I: ToSendValue,
1009 >(
1010 &mut self,
1011 name: impl AsRef<IdStr>,
1012 iter: impl IntoIterator<Item = I>,
1013 ) {
1014 let mut iter = iter.into_iter().peekable();
1015 if iter.peek().is_some() {
1016 let iter = iter.map(|item| item.to_send_value());
1017 self.set_with_id(name, V::from_iter(iter));
1018 }
1019 }
1020
1021 #[doc(alias = "gst_structure_set_value")]
1026 pub fn set_value(&mut self, name: impl IntoGStr, value: SendValue) {
1027 unsafe {
1028 name.run_with_gstr(|name| {
1029 ffi::gst_structure_take_value(&mut self.0, name.as_ptr(), &mut value.into_raw())
1030 });
1031 }
1032 }
1033
1034 #[doc(alias = "gst_structure_set_value_static_str")]
1039 pub fn set_value_with_static(&mut self, name: impl AsRef<GStr> + 'static, value: SendValue) {
1040 unsafe {
1041 cfg_if! {
1042 if #[cfg(feature = "v1_26")] {
1043 ffi::gst_structure_take_value_static_str(
1044 &mut self.0,
1045 name.as_ref().as_ptr(),
1046 &mut value.into_raw(),
1047 )
1048 } else {
1049 ffi::gst_structure_take_value(
1050 &mut self.0,
1051 name.as_ref().as_ptr(),
1052 &mut value.into_raw(),
1053 )
1054 }
1055 }
1056 }
1057 }
1058
1059 #[doc(alias = "gst_structure_id_str_set_value")]
1064 pub fn set_value_with_id(&mut self, name: impl AsRef<IdStr>, value: SendValue) {
1065 unsafe {
1066 cfg_if! {
1067 if #[cfg(feature = "v1_26")] {
1068 ffi::gst_structure_id_str_take_value(
1069 &mut self.0,
1070 name.as_ref().as_ptr(),
1071 &mut value.into_raw(),
1072 )
1073 } else {
1074 ffi::gst_structure_take_value(
1075 &mut self.0,
1076 name.as_ref().as_gstr().as_ptr(),
1077 &mut value.into_raw(),
1078 )
1079 }
1080 }
1081 }
1082 }
1083
1084 #[doc(alias = "gst_structure_set_value")]
1090 pub fn set_value_if(&mut self, name: impl IntoGStr, value: SendValue, predicate: bool) {
1091 if predicate {
1092 self.set_value(name, value);
1093 }
1094 }
1095
1096 #[doc(alias = "gst_structure_set_value_static_str")]
1102 pub fn set_value_with_static_if(
1103 &mut self,
1104 name: impl AsRef<GStr> + 'static,
1105 value: SendValue,
1106 predicate: bool,
1107 ) {
1108 if predicate {
1109 self.set_value_with_static(name, value);
1110 }
1111 }
1112
1113 #[doc(alias = "gst_structure_id_str_set_value")]
1119 pub fn set_value_with_id_if(
1120 &mut self,
1121 name: impl AsRef<IdStr>,
1122 value: SendValue,
1123 predicate: bool,
1124 ) {
1125 if predicate {
1126 self.set_value_with_id(name, value);
1127 }
1128 }
1129
1130 #[doc(alias = "gst_structure_set_value")]
1135 pub fn set_value_if_some(&mut self, name: impl IntoGStr, value: Option<SendValue>) {
1136 if let Some(value) = value {
1137 self.set_value(name, value);
1138 }
1139 }
1140
1141 #[doc(alias = "gst_structure_set_value_static_str")]
1146 pub fn set_value_with_static_if_some(
1147 &mut self,
1148 name: impl AsRef<GStr> + 'static,
1149 value: Option<SendValue>,
1150 ) {
1151 if let Some(value) = value {
1152 self.set_value_with_static(name, value);
1153 }
1154 }
1155
1156 #[doc(alias = "gst_structure_id_str_set_value")]
1161 pub fn set_value_with_id_if_some(&mut self, name: impl AsRef<IdStr>, value: Option<SendValue>) {
1162 if let Some(value) = value {
1163 self.set_value_with_id(name, value);
1164 }
1165 }
1166
1167 #[deprecated = "use `set_by_id()` instead"]
1168 #[allow(deprecated)]
1169 #[doc(alias = "gst_structure_id_set")]
1170 pub fn set_by_quark(&mut self, name: glib::Quark, value: impl Into<glib::Value> + Send) {
1171 let value = glib::SendValue::from_owned(value);
1172 self.set_value_by_quark(name, value);
1173 }
1174
1175 #[deprecated = "use `set_by_id_if_some()` instead"]
1176 #[allow(deprecated)]
1177 #[doc(alias = "gst_structure_id_set")]
1178 pub fn set_by_quark_if_some(
1179 &mut self,
1180 name: glib::Quark,
1181 value: Option<impl Into<glib::Value> + Send>,
1182 ) {
1183 if let Some(value) = value {
1184 self.set_by_quark(name, value);
1185 }
1186 }
1187
1188 #[deprecated = "use `set_by_id_value()` instead"]
1189 #[doc(alias = "gst_structure_id_set_value")]
1190 pub fn set_value_by_quark(&mut self, name: glib::Quark, value: SendValue) {
1191 unsafe {
1192 ffi::gst_structure_id_take_value(&mut self.0, name.into_glib(), &mut value.into_raw());
1193 }
1194 }
1195
1196 #[deprecated = "use `set_by_id_value_if_some()` instead"]
1197 #[allow(deprecated)]
1198 #[doc(alias = "gst_structure_id_set_value")]
1199 pub fn set_value_by_quark_if_some(&mut self, name: glib::Quark, value: Option<SendValue>) {
1200 if let Some(value) = value {
1201 self.set_value_by_quark(name, value);
1202 }
1203 }
1204
1205 #[doc(alias = "get_name")]
1206 #[doc(alias = "gst_structure_get_name")]
1207 pub fn name(&self) -> &glib::GStr {
1208 unsafe { glib::GStr::from_ptr(ffi::gst_structure_get_name(&self.0)) }
1209 }
1210
1211 #[cfg(feature = "v1_26")]
1212 #[doc(alias = "get_name")]
1213 #[doc(alias = "gst_structure_get_name_id_str")]
1214 pub fn name_id(&self) -> &IdStr {
1215 unsafe { &*(ffi::gst_structure_get_name_id_str(&self.0) as *const crate::IdStr) }
1216 }
1217
1218 #[deprecated = "use `name()` instead, or `name_id()` with feature v1_26"]
1219 #[doc(alias = "gst_structure_get_name_id")]
1220 pub fn name_quark(&self) -> glib::Quark {
1221 unsafe { from_glib(ffi::gst_structure_get_name_id(&self.0)) }
1222 }
1223
1224 #[doc(alias = "gst_structure_set_name")]
1225 pub fn set_name(&mut self, name: impl IntoGStr) {
1226 unsafe {
1227 name.run_with_gstr(|name| ffi::gst_structure_set_name(&mut self.0, name.as_ptr()))
1228 }
1229 }
1230
1231 #[doc(alias = "gst_structure_set_name_static_str")]
1232 pub fn set_name_from_static(&mut self, name: impl AsRef<GStr> + 'static) {
1233 unsafe {
1234 cfg_if! {
1235 if #[cfg(feature = "v1_26")] {
1236 ffi::gst_structure_set_name_static_str(
1237 &mut self.0,
1238 name.as_ref().as_ptr(),
1239 )
1240 } else {
1241 ffi::gst_structure_set_name(&mut self.0, name.as_ref().as_ptr())
1242 }
1243 }
1244 }
1245 }
1246
1247 #[doc(alias = "gst_structure_set_name_id_str")]
1248 pub fn set_name_from_id(&mut self, name: impl AsRef<IdStr>) {
1249 unsafe {
1250 cfg_if! {
1251 if #[cfg(feature = "v1_26")] {
1252 ffi::gst_structure_set_name_id_str(
1253 &mut self.0,
1254 name.as_ref().as_ptr(),
1255 )
1256 } else {
1257 ffi::gst_structure_set_name(&mut self.0, name.as_ref().as_gstr().as_ptr())
1258 }
1259 }
1260 }
1261 }
1262
1263 #[doc(alias = "gst_structure_set_name")]
1264 pub fn set_name_if_some(&mut self, name: Option<impl IntoGStr>) {
1265 if let Some(name) = name {
1266 self.set_name(name);
1267 }
1268 }
1269
1270 #[doc(alias = "gst_structure_set_name_static_str")]
1271 pub fn set_name_from_static_if_some(&mut self, name: Option<impl AsRef<GStr> + 'static>) {
1272 if let Some(name) = name {
1273 self.set_name_from_static(name);
1274 }
1275 }
1276
1277 #[doc(alias = "gst_structure_set_name_id_str")]
1278 pub fn set_name_from_id_if_some(&mut self, name: Option<impl AsRef<IdStr>>) {
1279 if let Some(name) = name {
1280 self.set_name_from_id(name);
1281 }
1282 }
1283
1284 #[doc(alias = "gst_structure_has_name")]
1285 pub fn has_name(&self, name: &str) -> bool {
1286 self.name() == name
1287 }
1288
1289 #[doc(alias = "gst_structure_has_field")]
1290 pub fn has_field(&self, field: impl IntoGStr) -> bool {
1291 unsafe {
1292 field.run_with_gstr(|field| {
1293 from_glib(ffi::gst_structure_has_field(&self.0, field.as_ptr()))
1294 })
1295 }
1296 }
1297
1298 #[doc(alias = "gst_structure_id_str_has_field")]
1299 pub fn has_field_by_id(&self, field: impl AsRef<IdStr>) -> bool {
1300 unsafe {
1301 cfg_if! {
1302 if #[cfg(feature = "v1_26")] {
1303 from_glib(ffi::gst_structure_id_str_has_field(
1304 &self.0,
1305 field.as_ref().as_ptr(),
1306 ))
1307 } else {
1308 from_glib(ffi::gst_structure_has_field(
1309 &self.0,
1310 field.as_ref().as_gstr().as_ptr(),
1311 ))
1312 }
1313 }
1314 }
1315 }
1316
1317 #[doc(alias = "gst_structure_has_field_typed")]
1318 pub fn has_field_with_type(&self, field: impl IntoGStr, type_: glib::Type) -> bool {
1319 unsafe {
1320 field.run_with_gstr(|field| {
1321 from_glib(ffi::gst_structure_has_field_typed(
1322 &self.0,
1323 field.as_ptr(),
1324 type_.into_glib(),
1325 ))
1326 })
1327 }
1328 }
1329
1330 #[doc(alias = "gst_structure_id_str_has_field_typed")]
1331 pub fn has_field_with_type_by_id(&self, field: impl AsRef<IdStr>, type_: glib::Type) -> bool {
1332 unsafe {
1333 cfg_if! {
1334 if #[cfg(feature = "v1_26")] {
1335 from_glib(ffi::gst_structure_id_str_has_field_typed(
1336 &self.0,
1337 field.as_ref().as_ptr(),
1338 type_.into_glib(),
1339 ))
1340 } else {
1341 from_glib(ffi::gst_structure_has_field_typed(
1342 &self.0,
1343 field.as_ref().as_gstr().as_ptr(),
1344 type_.into_glib(),
1345 ))
1346 }
1347 }
1348 }
1349 }
1350
1351 #[deprecated = "use `has_field_by_id()`"]
1352 #[doc(alias = "gst_structure_id_has_field")]
1353 pub fn has_field_by_quark(&self, field: glib::Quark) -> bool {
1354 unsafe { from_glib(ffi::gst_structure_id_has_field(&self.0, field.into_glib())) }
1355 }
1356
1357 #[deprecated = "use `has_field_with_type_by_id()`"]
1358 #[doc(alias = "gst_structure_id_has_field_typed")]
1359 pub fn has_field_with_type_by_quark(&self, field: glib::Quark, type_: glib::Type) -> bool {
1360 unsafe {
1361 from_glib(ffi::gst_structure_id_has_field_typed(
1362 &self.0,
1363 field.into_glib(),
1364 type_.into_glib(),
1365 ))
1366 }
1367 }
1368
1369 #[doc(alias = "gst_structure_remove_field")]
1370 pub fn remove_field(&mut self, field: impl IntoGStr) {
1371 unsafe {
1372 field.run_with_gstr(|field| {
1373 ffi::gst_structure_remove_field(&mut self.0, field.as_ptr())
1374 });
1375 }
1376 }
1377
1378 #[doc(alias = "gst_structure_remove_fields")]
1379 pub fn remove_fields<S: IntoGStr>(&mut self, fields: impl IntoIterator<Item = S>) {
1380 for f in fields.into_iter() {
1381 self.remove_field(f)
1382 }
1383 }
1384
1385 #[doc(alias = "gst_structure_id_str_remove_field")]
1386 pub fn remove_field_by_id(&mut self, field: impl AsRef<IdStr>) {
1387 unsafe {
1388 cfg_if! {
1389 if #[cfg(feature = "v1_26")] {
1390 ffi::gst_structure_id_str_remove_field(&mut self.0, field.as_ref().as_ptr())
1391 } else {
1392 ffi::gst_structure_remove_field(&mut self.0, field.as_ref().as_gstr().as_ptr())
1393 }
1394 }
1395 }
1396 }
1397
1398 #[doc(alias = "gst_structure_id_str_remove_fields")]
1399 pub fn remove_field_by_ids<S: AsRef<IdStr>>(&mut self, fields: impl IntoIterator<Item = S>) {
1400 for f in fields.into_iter() {
1401 self.remove_field_by_id(f)
1402 }
1403 }
1404
1405 #[doc(alias = "gst_structure_remove_all_fields")]
1406 pub fn remove_all_fields(&mut self) {
1407 unsafe {
1408 ffi::gst_structure_remove_all_fields(&mut self.0);
1409 }
1410 }
1411
1412 pub fn fields(&self) -> FieldIterator {
1413 FieldIterator::new(self)
1414 }
1415
1416 pub fn iter(&self) -> Iter {
1417 Iter::new(self)
1418 }
1419
1420 #[cfg(feature = "v1_26")]
1421 pub fn field_ids(&self) -> FieldIdIterator {
1422 FieldIdIterator::new(self)
1423 }
1424
1425 #[cfg(feature = "v1_26")]
1426 pub fn id_iter(&self) -> IdIter {
1427 IdIter::new(self)
1428 }
1429
1430 #[doc(alias = "get_nth_field_name")]
1431 #[doc(alias = "gst_structure_nth_field_name")]
1432 pub fn nth_field_name(&self, idx: usize) -> Option<&glib::GStr> {
1433 if idx >= self.n_fields() {
1434 return None;
1435 }
1436
1437 unsafe {
1438 let field_name = ffi::gst_structure_nth_field_name(&self.0, idx as u32);
1439 debug_assert!(!field_name.is_null());
1440
1441 Some(glib::GStr::from_ptr(field_name))
1442 }
1443 }
1444
1445 #[cfg(feature = "v1_26")]
1446 #[doc(alias = "get_nth_field_name")]
1447 #[doc(alias = "gst_structure_id_str_nth_field_name")]
1448 pub fn nth_field_by_id(&self, idx: usize) -> Option<&IdStr> {
1449 if idx >= self.n_fields() {
1450 return None;
1451 }
1452
1453 unsafe {
1454 let field_name = ffi::gst_structure_id_str_nth_field_name(&self.0, idx as u32);
1455 debug_assert!(!field_name.is_null());
1456
1457 Some(&*(field_name as *const crate::IdStr))
1458 }
1459 }
1460
1461 #[doc(alias = "gst_structure_n_fields")]
1462 pub fn n_fields(&self) -> usize {
1463 unsafe { ffi::gst_structure_n_fields(&self.0) as usize }
1464 }
1465
1466 pub fn len(&self) -> usize {
1467 self.n_fields()
1468 }
1469
1470 pub fn is_empty(&self) -> bool {
1471 self.n_fields() == 0
1472 }
1473
1474 #[doc(alias = "gst_structure_can_intersect")]
1475 pub fn can_intersect(&self, other: &StructureRef) -> bool {
1476 unsafe { from_glib(ffi::gst_structure_can_intersect(&self.0, &other.0)) }
1477 }
1478
1479 #[doc(alias = "gst_structure_intersect")]
1480 pub fn intersect(&self, other: &StructureRef) -> Option<Structure> {
1481 unsafe { from_glib_full(ffi::gst_structure_intersect(&self.0, &other.0)) }
1482 }
1483
1484 #[doc(alias = "gst_structure_is_subset")]
1485 pub fn is_subset(&self, superset: &StructureRef) -> bool {
1486 unsafe { from_glib(ffi::gst_structure_is_subset(&self.0, &superset.0)) }
1487 }
1488
1489 #[doc(alias = "gst_structure_fixate")]
1490 pub fn fixate(&mut self) {
1491 unsafe { ffi::gst_structure_fixate(&mut self.0) }
1492 }
1493
1494 #[doc(alias = "gst_structure_fixate_field")]
1495 pub fn fixate_field(&mut self, name: impl IntoGStr) -> bool {
1496 unsafe {
1497 name.run_with_gstr(|name| {
1498 from_glib(ffi::gst_structure_fixate_field(&mut self.0, name.as_ptr()))
1499 })
1500 }
1501 }
1502
1503 #[doc(alias = "gst_structure_fixate_field_boolean")]
1504 pub fn fixate_field_bool(&mut self, name: impl IntoGStr, target: bool) -> bool {
1505 unsafe {
1506 name.run_with_gstr(|name| {
1507 from_glib(ffi::gst_structure_fixate_field_boolean(
1508 &mut self.0,
1509 name.as_ptr(),
1510 target.into_glib(),
1511 ))
1512 })
1513 }
1514 }
1515
1516 #[doc(alias = "gst_structure_fixate_field_string")]
1517 pub fn fixate_field_str(&mut self, name: impl IntoGStr, target: impl IntoGStr) -> bool {
1518 unsafe {
1519 name.run_with_gstr(|name| {
1520 target.run_with_gstr(|target| {
1521 from_glib(ffi::gst_structure_fixate_field_string(
1522 &mut self.0,
1523 name.as_ptr(),
1524 target.as_ptr(),
1525 ))
1526 })
1527 })
1528 }
1529 }
1530
1531 #[doc(alias = "gst_structure_fixate_field_nearest_double")]
1532 pub fn fixate_field_nearest_double(&mut self, name: impl IntoGStr, target: f64) -> bool {
1533 unsafe {
1534 name.run_with_gstr(|name| {
1535 from_glib(ffi::gst_structure_fixate_field_nearest_double(
1536 &mut self.0,
1537 name.as_ptr(),
1538 target,
1539 ))
1540 })
1541 }
1542 }
1543
1544 #[doc(alias = "gst_structure_fixate_field_nearest_fraction")]
1545 pub fn fixate_field_nearest_fraction(
1546 &mut self,
1547 name: impl IntoGStr,
1548 target: impl Into<Fraction>,
1549 ) -> bool {
1550 skip_assert_initialized!();
1551
1552 let target = target.into();
1553 unsafe {
1554 name.run_with_gstr(|name| {
1555 from_glib(ffi::gst_structure_fixate_field_nearest_fraction(
1556 &mut self.0,
1557 name.as_ptr(),
1558 target.numer(),
1559 target.denom(),
1560 ))
1561 })
1562 }
1563 }
1564
1565 #[doc(alias = "gst_structure_fixate_field_nearest_int")]
1566 pub fn fixate_field_nearest_int(&mut self, name: impl IntoGStr, target: i32) -> bool {
1567 unsafe {
1568 name.run_with_gstr(|name| {
1569 from_glib(ffi::gst_structure_fixate_field_nearest_int(
1570 &mut self.0,
1571 name.as_ptr(),
1572 target,
1573 ))
1574 })
1575 }
1576 }
1577
1578 #[cfg(feature = "v1_20")]
1579 #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
1580 #[doc(alias = "gst_structure_serialize")]
1581 pub fn serialize(&self, flags: crate::SerializeFlags) -> glib::GString {
1582 unsafe { from_glib_full(ffi::gst_structure_serialize(&self.0, flags.into_glib())) }
1583 }
1584
1585 #[cfg(feature = "v1_24")]
1586 #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1587 #[doc(alias = "gst_structure_serialize")]
1588 #[doc(alias = "gst_structure_serialize_full")]
1589 pub fn serialize_strict(
1590 &self,
1591 flags: crate::SerializeFlags,
1592 ) -> Result<glib::GString, glib::BoolError> {
1593 unsafe {
1594 let res = ffi::gst_structure_serialize_full(
1595 &self.0,
1596 flags.into_glib() | ffi::GST_SERIALIZE_FLAG_STRICT,
1597 );
1598 if res.is_null() {
1599 Err(glib::bool_error!("Failed to serialize structure to string"))
1600 } else {
1601 Ok(from_glib_full(res))
1602 }
1603 }
1604 }
1605
1606 #[deprecated = "Use `iter()` instead, or `id_iter()` with feature v1_26"]
1607 #[doc(alias = "gst_structure_foreach")]
1608 pub fn foreach<F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>>(
1609 &self,
1610 mut func: F,
1611 ) -> bool {
1612 unsafe {
1613 unsafe extern "C" fn trampoline<
1614 F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>,
1615 >(
1616 quark: glib::ffi::GQuark,
1617 value: *const glib::gobject_ffi::GValue,
1618 user_data: glib::ffi::gpointer,
1619 ) -> glib::ffi::gboolean {
1620 let func = &mut *(user_data as *mut F);
1621 let res = func(from_glib(quark), &*(value as *const glib::Value));
1622
1623 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1624 }
1625 let func = &mut func as *mut F;
1626 from_glib(ffi::gst_structure_foreach(
1627 self.as_ptr(),
1628 Some(trampoline::<F>),
1629 func as glib::ffi::gpointer,
1630 ))
1631 }
1632 }
1633
1634 #[cfg(feature = "v1_26")]
1635 #[doc(alias = "gst_structure_map_in_place_id_str")]
1638 pub fn map_in_place_by_id<F: FnMut(&IdStr, &mut glib::Value) -> std::ops::ControlFlow<()>>(
1639 &mut self,
1640 mut func: F,
1641 ) {
1642 unsafe {
1643 unsafe extern "C" fn trampoline<
1644 F: FnMut(&IdStr, &mut glib::Value) -> std::ops::ControlFlow<()>,
1645 >(
1646 fieldname: *const ffi::GstIdStr,
1647 value: *mut glib::gobject_ffi::GValue,
1648 user_data: glib::ffi::gpointer,
1649 ) -> glib::ffi::gboolean {
1650 let func = &mut *(user_data as *mut F);
1651 let res = func(
1652 &*(fieldname as *const IdStr),
1653 &mut *(value as *mut glib::Value),
1654 );
1655
1656 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1657 }
1658 let func = &mut func as *mut F;
1659 let _ = ffi::gst_structure_map_in_place_id_str(
1660 self.as_mut_ptr(),
1661 Some(trampoline::<F>),
1662 func as glib::ffi::gpointer,
1663 );
1664 }
1665 }
1666
1667 #[cfg(feature = "v1_26")]
1668 #[doc(alias = "gst_structure_filter_and_map_in_place_id_str")]
1675 pub fn filter_map_in_place_by_id<F: FnMut(&IdStr, glib::Value) -> Option<glib::Value>>(
1676 &mut self,
1677 mut func: F,
1678 ) {
1679 unsafe {
1680 unsafe extern "C" fn trampoline<
1681 F: FnMut(&IdStr, glib::Value) -> Option<glib::Value>,
1682 >(
1683 fieldname: *const ffi::GstIdStr,
1684 value: *mut glib::gobject_ffi::GValue,
1685 user_data: glib::ffi::gpointer,
1686 ) -> glib::ffi::gboolean {
1687 let func = &mut *(user_data as *mut F);
1688
1689 let v = mem::replace(
1690 &mut *(value as *mut glib::Value),
1691 glib::Value::uninitialized(),
1692 );
1693 match func(&*(fieldname as *const IdStr), v) {
1694 None => glib::ffi::GFALSE,
1695 Some(v) => {
1696 *value = v.into_raw();
1697 glib::ffi::GTRUE
1698 }
1699 }
1700 }
1701
1702 let func = &mut func as *mut F;
1703 ffi::gst_structure_filter_and_map_in_place_id_str(
1704 self.as_mut_ptr(),
1705 Some(trampoline::<F>),
1706 func as glib::ffi::gpointer,
1707 );
1708 }
1709 }
1710
1711 #[doc(alias = "gst_structure_map_in_place")]
1726 pub fn map_in_place<F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>>(
1727 &mut self,
1728 mut func: F,
1729 ) -> std::ops::ControlFlow<()> {
1730 unsafe {
1731 unsafe extern "C" fn trampoline<
1732 F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>,
1733 >(
1734 quark: glib::ffi::GQuark,
1735 value: *mut glib::gobject_ffi::GValue,
1736 user_data: glib::ffi::gpointer,
1737 ) -> glib::ffi::gboolean {
1738 let func = &mut *(user_data as *mut F);
1739 let res = func(from_glib(quark), &mut *(value as *mut glib::Value));
1740
1741 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1742 }
1743 let func = &mut func as *mut F;
1744 if from_glib(ffi::gst_structure_map_in_place(
1745 self.as_mut_ptr(),
1746 Some(trampoline::<F>),
1747 func as glib::ffi::gpointer,
1748 )) {
1749 std::ops::ControlFlow::Continue(())
1750 } else {
1751 std::ops::ControlFlow::Break(())
1752 }
1753 }
1754 }
1755
1756 #[doc(alias = "gst_structure_filter_and_map_in_place")]
1769 pub fn filter_map_in_place<F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>>(
1770 &mut self,
1771 mut func: F,
1772 ) {
1773 unsafe {
1774 unsafe extern "C" fn trampoline<
1775 F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>,
1776 >(
1777 quark: glib::ffi::GQuark,
1778 value: *mut glib::gobject_ffi::GValue,
1779 user_data: glib::ffi::gpointer,
1780 ) -> glib::ffi::gboolean {
1781 let func = &mut *(user_data as *mut F);
1782
1783 let v = mem::replace(
1784 &mut *(value as *mut glib::Value),
1785 glib::Value::uninitialized(),
1786 );
1787 match func(from_glib(quark), v) {
1788 None => glib::ffi::GFALSE,
1789 Some(v) => {
1790 *value = v.into_raw();
1791 glib::ffi::GTRUE
1792 }
1793 }
1794 }
1795
1796 let func = &mut func as *mut F;
1797 ffi::gst_structure_filter_and_map_in_place(
1798 self.as_mut_ptr(),
1799 Some(trampoline::<F>),
1800 func as glib::ffi::gpointer,
1801 );
1802 }
1803 }
1804}
1805
1806impl fmt::Display for StructureRef {
1807 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1808 let s = unsafe { glib::GString::from_glib_full(ffi::gst_structure_to_string(&self.0)) };
1809 f.write_str(&s)
1810 }
1811}
1812
1813impl fmt::Debug for StructureRef {
1814 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1815 let mut debug = f.debug_struct(self.name());
1816
1817 for (id, field) in self.iter() {
1818 if field.type_() == Structure::static_type() {
1819 let s = field.get::<Structure>().unwrap();
1820 debug.field(id, &s);
1821 } else if field.type_() == crate::Array::static_type() {
1822 let arr = field.get::<crate::Array>().unwrap();
1823 debug.field(id, &arr);
1824 } else if field.type_() == crate::List::static_type() {
1825 let list = field.get::<crate::List>().unwrap();
1826 debug.field(id, &list);
1827 } else {
1828 debug.field(id, &field);
1829 }
1830 }
1831
1832 debug.finish()
1833 }
1834}
1835
1836impl PartialEq for StructureRef {
1837 #[doc(alias = "gst_structure_is_equal")]
1838 fn eq(&self, other: &StructureRef) -> bool {
1839 unsafe { from_glib(ffi::gst_structure_is_equal(&self.0, &other.0)) }
1840 }
1841}
1842
1843impl Eq for StructureRef {}
1844
1845impl glib::types::StaticType for StructureRef {
1846 #[inline]
1847 fn static_type() -> glib::types::Type {
1848 unsafe { from_glib(ffi::gst_structure_get_type()) }
1849 }
1850}
1851
1852unsafe impl<'a> glib::value::FromValue<'a> for &'a StructureRef {
1853 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
1854
1855 unsafe fn from_value(value: &'a glib::Value) -> Self {
1856 skip_assert_initialized!();
1857 &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const StructureRef)
1858 }
1859}
1860
1861impl glib::value::ToValue for StructureRef {
1862 fn to_value(&self) -> glib::Value {
1863 let mut value = glib::Value::for_value_type::<Structure>();
1864 unsafe {
1865 glib::gobject_ffi::g_value_set_boxed(
1866 value.to_glib_none_mut().0,
1867 self.as_ptr() as *mut _,
1868 )
1869 }
1870 value
1871 }
1872
1873 fn value_type(&self) -> glib::Type {
1874 Self::static_type()
1875 }
1876}
1877
1878impl glib::value::ToValueOptional for StructureRef {
1879 fn to_value_optional(s: Option<&Self>) -> glib::Value {
1880 skip_assert_initialized!();
1881 let mut value = glib::Value::for_value_type::<Structure>();
1882 unsafe {
1883 glib::gobject_ffi::g_value_set_boxed(
1884 value.to_glib_none_mut().0,
1885 s.map(|s| s.as_ptr()).unwrap_or(ptr::null()) as *mut _,
1886 )
1887 }
1888 value
1889 }
1890}
1891
1892crate::utils::define_fixed_size_iter!(
1893 FieldIterator,
1894 &'a StructureRef,
1895 &'a glib::GStr,
1896 |collection: &StructureRef| collection.n_fields(),
1897 |collection: &StructureRef, idx: usize| unsafe {
1898 let field_name = ffi::gst_structure_nth_field_name(&collection.0, idx as u32);
1899 glib::GStr::from_ptr(field_name)
1900 }
1901);
1902
1903#[cfg(feature = "v1_26")]
1904crate::utils::define_fixed_size_iter!(
1905 FieldIdIterator,
1906 &'a StructureRef,
1907 &'a crate::IdStr,
1908 |collection: &StructureRef| collection.n_fields(),
1909 |collection: &StructureRef, idx: usize| unsafe {
1910 let field_name = ffi::gst_structure_id_str_nth_field_name(&collection.0, idx as u32);
1911 debug_assert!(!field_name.is_null());
1912
1913 &*(field_name as *const crate::IdStr)
1914 }
1915);
1916
1917#[must_use = "iterators are lazy and do nothing unless consumed"]
1918#[derive(Debug)]
1919pub struct Iter<'a> {
1920 iter: FieldIterator<'a>,
1921}
1922
1923impl<'a> Iter<'a> {
1924 fn new(structure: &'a StructureRef) -> Iter<'a> {
1925 skip_assert_initialized!();
1926 Iter {
1927 iter: FieldIterator::new(structure),
1928 }
1929 }
1930}
1931
1932impl<'a> Iterator for Iter<'a> {
1933 type Item = (&'a glib::GStr, &'a SendValue);
1934
1935 fn next(&mut self) -> Option<Self::Item> {
1936 let f = self.iter.next()?;
1937 let v = self.iter.collection.value(f);
1938 Some((f, v.unwrap()))
1939 }
1940
1941 fn size_hint(&self) -> (usize, Option<usize>) {
1942 self.iter.size_hint()
1943 }
1944
1945 fn count(self) -> usize {
1946 self.iter.count()
1947 }
1948
1949 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1950 let f = self.iter.nth(n)?;
1951 let v = self.iter.collection.value(f);
1952 Some((f, v.unwrap()))
1953 }
1954
1955 fn last(self) -> Option<Self::Item> {
1956 let structure = self.iter.collection;
1957 let f = self.iter.last()?;
1958 let v = structure.value(f);
1959 Some((f, v.unwrap()))
1960 }
1961}
1962
1963impl DoubleEndedIterator for Iter<'_> {
1964 fn next_back(&mut self) -> Option<Self::Item> {
1965 let f = self.iter.next_back()?;
1966 let v = self.iter.collection.value(f);
1967 Some((f, v.unwrap()))
1968 }
1969
1970 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1971 let f = self.iter.nth_back(n)?;
1972 let v = self.iter.collection.value(f);
1973 Some((f, v.unwrap()))
1974 }
1975}
1976
1977impl ExactSizeIterator for Iter<'_> {}
1978
1979impl std::iter::FusedIterator for Iter<'_> {}
1980
1981#[cfg(feature = "v1_26")]
1982#[must_use = "iterators are lazy and do nothing unless consumed"]
1983#[derive(Debug)]
1984pub struct IdIter<'a> {
1985 iter: FieldIdIterator<'a>,
1986}
1987
1988#[cfg(feature = "v1_26")]
1989impl<'a> IdIter<'a> {
1990 fn new(structure: &'a StructureRef) -> IdIter<'a> {
1991 skip_assert_initialized!();
1992 IdIter {
1993 iter: FieldIdIterator::new(structure),
1994 }
1995 }
1996}
1997
1998#[cfg(feature = "v1_26")]
1999impl<'a> Iterator for IdIter<'a> {
2000 type Item = (&'a IdStr, &'a SendValue);
2001
2002 fn next(&mut self) -> Option<Self::Item> {
2003 let f = self.iter.next()?;
2004 let v = self.iter.collection.value_by_id(f);
2005 Some((f, v.unwrap()))
2006 }
2007
2008 fn size_hint(&self) -> (usize, Option<usize>) {
2009 self.iter.size_hint()
2010 }
2011
2012 fn count(self) -> usize {
2013 self.iter.count()
2014 }
2015
2016 fn nth(&mut self, n: usize) -> Option<Self::Item> {
2017 let f = self.iter.nth(n)?;
2018 let v = self.iter.collection.value_by_id(f);
2019 Some((f, v.unwrap()))
2020 }
2021
2022 fn last(self) -> Option<Self::Item> {
2023 let structure = self.iter.collection;
2024 let f = self.iter.last()?;
2025 let v = structure.value_by_id(f);
2026 Some((f, v.unwrap()))
2027 }
2028}
2029
2030#[cfg(feature = "v1_26")]
2031impl DoubleEndedIterator for IdIter<'_> {
2032 fn next_back(&mut self) -> Option<Self::Item> {
2033 let f = self.iter.next_back()?;
2034 let v = self.iter.collection.value_by_id(f);
2035 Some((f, v.unwrap()))
2036 }
2037
2038 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
2039 let f = self.iter.nth_back(n)?;
2040 let v = self.iter.collection.value_by_id(f);
2041 Some((f, v.unwrap()))
2042 }
2043}
2044
2045#[cfg(feature = "v1_26")]
2046impl ExactSizeIterator for IdIter<'_> {}
2047#[cfg(feature = "v1_26")]
2048impl std::iter::FusedIterator for IdIter<'_> {}
2049
2050impl<'a> IntoIterator for &'a StructureRef {
2051 type IntoIter = Iter<'a>;
2052 type Item = (&'a glib::GStr, &'a SendValue);
2053
2054 fn into_iter(self) -> Self::IntoIter {
2055 self.iter()
2056 }
2057}
2058
2059impl<'a> std::iter::Extend<(&'a str, SendValue)> for StructureRef {
2060 fn extend<T: IntoIterator<Item = (&'a str, SendValue)>>(&mut self, iter: T) {
2061 iter.into_iter().for_each(|(f, v)| self.set_value(f, v));
2062 }
2063}
2064
2065impl<'a> std::iter::Extend<(&'a glib::GStr, SendValue)> for StructureRef {
2066 fn extend<T: IntoIterator<Item = (&'a glib::GStr, SendValue)>>(&mut self, iter: T) {
2067 iter.into_iter().for_each(|(f, v)| self.set_value(f, v));
2068 }
2069}
2070
2071impl std::iter::Extend<(String, SendValue)> for StructureRef {
2072 fn extend<T: IntoIterator<Item = (String, SendValue)>>(&mut self, iter: T) {
2073 iter.into_iter().for_each(|(f, v)| self.set_value(&f, v));
2074 }
2075}
2076
2077impl std::iter::Extend<(glib::GString, SendValue)> for StructureRef {
2078 fn extend<T: IntoIterator<Item = (glib::GString, SendValue)>>(&mut self, iter: T) {
2079 iter.into_iter().for_each(|(f, v)| self.set_value(&f, v));
2080 }
2081}
2082
2083impl<'a> std::iter::Extend<(&'a IdStr, SendValue)> for StructureRef {
2084 #[allow(deprecated)]
2085 fn extend<T: IntoIterator<Item = (&'a IdStr, SendValue)>>(&mut self, iter: T) {
2086 iter.into_iter()
2087 .for_each(|(f, v)| self.set_value_with_id(f, v));
2088 }
2089}
2090
2091impl std::iter::Extend<(IdStr, SendValue)> for StructureRef {
2092 #[allow(deprecated)]
2093 fn extend<T: IntoIterator<Item = (IdStr, SendValue)>>(&mut self, iter: T) {
2094 iter.into_iter()
2095 .for_each(|(f, v)| self.set_value_with_id(f, v));
2096 }
2097}
2098
2099impl std::iter::Extend<(glib::Quark, SendValue)> for StructureRef {
2100 #[allow(deprecated)]
2101 fn extend<T: IntoIterator<Item = (glib::Quark, SendValue)>>(&mut self, iter: T) {
2102 iter.into_iter()
2103 .for_each(|(f, v)| self.set_value_by_quark(f, v));
2104 }
2105}
2106
2107#[cfg(feature = "v1_28")]
2109impl std::hash::Hash for StructureRef {
2110 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2111 use crate::value::GstValueExt;
2112 use std::hash::{DefaultHasher, Hasher};
2113
2114 let name = self.name();
2115 name.hash(state);
2116
2117 let mut fields_hash = 0;
2119 for (field, value) in self.iter() {
2120 let mut field_hasher = DefaultHasher::new();
2121 field.hash(&mut field_hasher);
2122 let value_hash = value.hash().unwrap();
2123 value_hash.hash(&mut field_hasher);
2124
2125 fields_hash ^= field_hasher.finish();
2126 }
2127 fields_hash.hash(state);
2128 }
2129}
2130
2131#[cfg(feature = "v1_28")]
2132impl std::hash::Hash for Structure {
2133 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2134 self.as_ref().hash(state);
2135 }
2136}
2137
2138#[derive(Debug)]
2139#[must_use = "The builder must be built to be used"]
2140pub struct Builder {
2141 s: Structure,
2142}
2143
2144impl Builder {
2145 fn new(name: impl IntoGStr) -> Self {
2146 skip_assert_initialized!();
2147 Builder {
2148 s: Structure::new_empty(name),
2149 }
2150 }
2151
2152 fn from_static(name: impl AsRef<GStr> + 'static) -> Self {
2153 skip_assert_initialized!();
2154 Builder {
2155 s: Structure::new_empty_from_static(name),
2156 }
2157 }
2158
2159 pub fn from_id(name: impl AsRef<IdStr>) -> Builder {
2160 skip_assert_initialized!();
2161 Builder {
2162 s: Structure::new_empty_from_id(name),
2163 }
2164 }
2165
2166 #[inline]
2171 pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self {
2172 self.s.set(name, value);
2173 self
2174 }
2175
2176 #[inline]
2181 pub fn field_with_static(
2182 mut self,
2183 name: impl AsRef<GStr> + 'static,
2184 value: impl Into<glib::Value> + Send,
2185 ) -> Self {
2186 self.s.set_with_static(name, value);
2187 self
2188 }
2189
2190 #[inline]
2195 pub fn field_with_id(
2196 mut self,
2197 name: impl AsRef<IdStr>,
2198 value: impl Into<glib::Value> + Send,
2199 ) -> Self {
2200 self.s.set_with_id(name, value);
2201 self
2202 }
2203
2204 impl_builder_gvalue_extra_setters!(field);
2205
2206 #[must_use = "Building the structure without using it has no effect"]
2207 pub fn build(self) -> Structure {
2208 self.s
2209 }
2210}
2211
2212#[cfg(test)]
2213mod tests {
2214 use super::*;
2215 use glib::gstr;
2216
2217 #[test]
2218 fn new_set_get() {
2219 use glib::{value, Type};
2220
2221 crate::init().unwrap();
2222
2223 let mut s = Structure::new_empty("test");
2224 assert_eq!(s.name(), "test");
2225
2226 s.set("f1", "abc");
2227 s.set("f2", String::from("bcd"));
2228 s.set("f3", 123i32);
2229 s.set("f5", Some("efg"));
2230 s.set("f7", 42i32);
2231
2232 assert_eq!(s.get::<&str>("f1"), Ok("abc"));
2233 assert_eq!(s.get::<Option<&str>>("f2"), Ok(Some("bcd")));
2234 assert_eq!(s.get::<i32>("f3"), Ok(123i32));
2235 assert_eq!(s.get_optional::<&str>("f1"), Ok(Some("abc")));
2236 assert_eq!(s.get_optional::<&str>("f4"), Ok(None));
2237 assert_eq!(s.get_optional::<i32>("f3"), Ok(Some(123i32)));
2238 assert_eq!(s.get_optional::<i32>("f4"), Ok(None));
2239 assert_eq!(s.get::<&str>("f5"), Ok("efg"));
2240 assert_eq!(s.get::<i32>("f7"), Ok(42i32));
2241
2242 assert_eq!(
2243 s.get::<i32>("f2"),
2244 Err(GetError::from_value_get_error(
2245 idstr!("f2"),
2246 value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
2247 ))
2248 );
2249 assert_eq!(
2250 s.get::<bool>("f3"),
2251 Err(GetError::from_value_get_error(
2252 idstr!("f3"),
2253 value::ValueTypeMismatchError::new(Type::I32, Type::BOOL),
2254 ))
2255 );
2256 assert_eq!(
2257 s.get::<&str>("f4"),
2258 Err(GetError::new_field_not_found(idstr!("f4")))
2259 );
2260 assert_eq!(
2261 s.get::<i32>("f4"),
2262 Err(GetError::new_field_not_found(idstr!("f4")))
2263 );
2264
2265 assert_eq!(
2266 s.fields().collect::<Vec<_>>(),
2267 vec!["f1", "f2", "f3", "f5", "f7"]
2268 );
2269
2270 let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>();
2271 assert_eq!(v.len(), 5);
2272 assert_eq!(v[0].0, "f1");
2273 assert_eq!(v[0].1.get::<&str>(), Ok("abc"));
2274 assert_eq!(v[1].0, "f2");
2275 assert_eq!(v[1].1.get::<&str>(), Ok("bcd"));
2276 assert_eq!(v[2].0, "f3");
2277 assert_eq!(v[2].1.get::<i32>(), Ok(123i32));
2278 assert_eq!(v[3].0, "f5");
2279 assert_eq!(v[3].1.get::<&str>(), Ok("efg"));
2280 assert_eq!(v[4].0, "f7");
2281 assert_eq!(v[4].1.get::<i32>(), Ok(42i32));
2282
2283 let s2 = Structure::builder("test")
2284 .field("f1", "abc")
2285 .field("f2", String::from("bcd"))
2286 .field("f3", 123i32)
2287 .field_if_some("f4", Option::<i32>::None)
2288 .field_if_some("f5", Some("efg"))
2289 .field_if_some("f6", Option::<&str>::None)
2290 .field_if("f7", 42i32, true)
2291 .field_if("f8", 21i32, false)
2292 .build();
2293 assert_eq!(s, s2);
2294
2295 let mut s3 = Structure::new_empty("test");
2296
2297 s3.set_if_some("f1", Some("abc"));
2298 s3.set_if_some("f2", Some(String::from("bcd")));
2299 s3.set_if_some("f3", Some(123i32));
2300 s3.set_if_some("f4", Option::<i32>::None);
2301 s3.set_if_some("f5", Some("efg"));
2302 s3.set_if_some("f6", Option::<&str>::None);
2303 s3.set_if("f7", 42i32, true);
2304 s3.set_if("f8", 21i32, false);
2305 assert_eq!(s, s3);
2306 }
2307
2308 #[test]
2309 fn new_set_get_static() {
2310 use glib::{value, Type};
2311
2312 crate::init().unwrap();
2313
2314 let mut s = Structure::new_empty_from_static(gstr!("test"));
2315 assert_eq!(s.name(), "test");
2316
2317 static F1: &GStr = gstr!("f1");
2318 static F2: &GStr = gstr!("f2");
2319 static F3: &GStr = gstr!("f3");
2320
2321 s.set_with_static(F1, "abc");
2322 s.set_with_static_if(F2, String::from("bcd"), true);
2323 s.set_with_static_if(F3, "not_set", false);
2324
2325 assert_eq!(s.get::<&str>(F1), Ok("abc"));
2326 assert_eq!(s.get::<Option<&str>>(F2), Ok(Some("bcd")));
2327 assert_eq!(s.get_optional::<&str>(F1), Ok(Some("abc")));
2328 assert_eq!(s.get_optional::<&str>(F3), Ok(None));
2329
2330 assert_eq!(
2331 s.get::<i32>(F2),
2332 Err(GetError::from_value_get_error(
2333 idstr!("f2"),
2334 value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
2335 ))
2336 );
2337 assert_eq!(
2338 s.get::<&str>(F3),
2339 Err(GetError::new_field_not_found(idstr!("f3")))
2340 );
2341
2342 let s2 = Structure::builder("test")
2343 .field_with_static(F1, "abc")
2344 .field_with_static(F2, String::from("bcd"))
2345 .build();
2346 assert_eq!(s, s2);
2347
2348 let mut s3 = Structure::new_empty("test");
2349
2350 s3.set_with_static_if_some(F1, Some("abc"));
2351 s3.set_with_static_if_some(F2, Some(String::from("bcd")));
2352
2353 assert_eq!(s, s3);
2354 }
2355
2356 #[test]
2357 fn new_set_get_id_str() {
2358 use glib::{value, Type};
2359
2360 crate::init().unwrap();
2361
2362 let mut s = Structure::new_empty_from_id(idstr!("test"));
2363 assert_eq!(s.name(), "test");
2364 #[cfg(feature = "v1_26")]
2365 assert_eq!(s.name_id(), "test");
2366
2367 let f1 = idstr!("f1");
2368 let f2 = idstr!("f2");
2369 let f3 = idstr!("f3");
2370
2371 s.set_with_id(&f1, "abc");
2372 s.set_with_id_if(&f2, String::from("bcd"), true);
2373 s.set_with_id_if(&f3, "not_set", false);
2374
2375 assert_eq!(s.get_by_id::<&str>(&f1), Ok("abc"));
2376 assert_eq!(s.get_by_id::<&str>(f1.clone()), Ok("abc"));
2377 assert_eq!(s.get_by_id::<Option<&str>>(&f2), Ok(Some("bcd")));
2378 assert_eq!(s.get_by_id::<Option<&str>>(f2.clone()), Ok(Some("bcd")));
2379 assert_eq!(s.get_optional_by_id::<&str>(&f1), Ok(Some("abc")));
2380 assert_eq!(s.get_optional_by_id::<&str>(&f3), Ok(None));
2381
2382 assert_eq!(
2383 s.get_by_id::<i32>(&f2),
2384 Err(GetError::from_value_get_error(
2385 f2.clone(),
2386 value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
2387 ))
2388 );
2389 assert_eq!(
2390 s.get_by_id::<&str>(&f3),
2391 Err(GetError::new_field_not_found(f3.clone()))
2392 );
2393
2394 let s2 = Structure::builder("test")
2395 .field_with_id(&f1, "abc")
2396 .field_with_id(&f2, String::from("bcd"))
2397 .build();
2398 assert_eq!(s, s2);
2399
2400 let mut s3 = Structure::new_empty("test");
2401
2402 s3.set_with_id_if_some(f1, Some("abc"));
2403 s3.set_with_id_if_some(f2, Some(String::from("bcd")));
2404
2405 assert_eq!(s, s3);
2406 }
2407
2408 #[test]
2409 fn test_string_conversion() {
2410 crate::init().unwrap();
2411
2412 let a = "Test, f1=(string)abc, f2=(uint)123;";
2413
2414 let s = a.parse::<Structure>().unwrap();
2415 assert_eq!(s.get::<&str>("f1"), Ok("abc"));
2416 assert_eq!(s.get::<u32>("f2"), Ok(123));
2417
2418 assert_eq!(a, s.to_string());
2419 }
2420
2421 #[test]
2422 fn test_from_value_optional() {
2423 use glib::value::ToValue;
2424
2425 crate::init().unwrap();
2426
2427 let a = None::<&Structure>.to_value();
2428 assert!(a.get::<Option<Structure>>().unwrap().is_none());
2429 let b = "foo".parse::<Structure>().unwrap().to_value();
2430 assert!(b.get::<Option<Structure>>().unwrap().is_some());
2431 }
2432
2433 #[test]
2434 fn test_new_from_iter() {
2435 crate::init().unwrap();
2436
2437 let s = Structure::builder("test")
2438 .field("f1", "abc")
2439 .field_with_static(gstr!("f2"), String::from("bcd"))
2440 .field_with_id(idstr!("f3"), 123i32)
2441 .build();
2442
2443 let s2 = Structure::from_iter(
2444 s.name(),
2445 s.iter()
2446 .filter(|(f, _)| *f == "f1")
2447 .map(|(f, v)| (f, v.clone())),
2448 );
2449
2450 assert_eq!(s2.name(), "test");
2451 assert_eq!(s2.get::<&str>("f1"), Ok("abc"));
2452 assert!(s2.get::<&str>("f2").is_err());
2453 assert!(s2.get_by_id::<&str>(idstr!("f3")).is_err());
2454 }
2455
2456 #[test]
2457 fn test_debug() {
2458 crate::init().unwrap();
2459
2460 let s = Structure::builder("test")
2461 .field("f1", "abc")
2462 .field("f2", String::from("bcd"))
2463 .field("f3", 123i32)
2464 .field(
2465 "f4",
2466 Structure::builder("nested").field("badger", true).build(),
2467 )
2468 .field("f5", crate::Array::new(["a", "b", "c"]))
2469 .field("f6", crate::List::new(["d", "e", "f"]))
2470 .build();
2471
2472 assert_eq!(format!("{s:?}"), "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\"]) })");
2473 }
2474
2475 #[test]
2476 fn builder_field_from_iter() {
2477 crate::init().unwrap();
2478
2479 static SLIST: &GStr = gstr!("slist");
2480 let ilist = idstr!("ilist");
2481 let s = Structure::builder("test")
2482 .field_from_iter::<crate::Array, i32>("array", [1, 2, 3])
2483 .field_with_static_from_iter::<crate::List, i32>(SLIST, [4, 5, 6])
2484 .field_with_id_from_iter::<crate::List, i32>(&ilist, [7, 8, 9])
2485 .build();
2486 assert!(s
2487 .get::<crate::Array>("array")
2488 .unwrap()
2489 .iter()
2490 .map(|val| val.get::<i32>().unwrap())
2491 .eq([1, 2, 3]));
2492 assert!(s
2493 .get::<crate::List>("slist")
2494 .unwrap()
2495 .iter()
2496 .map(|val| val.get::<i32>().unwrap())
2497 .eq([4, 5, 6]));
2498 assert!(s
2499 .get_by_id::<crate::List>(&ilist)
2500 .unwrap()
2501 .iter()
2502 .map(|val| val.get::<i32>().unwrap())
2503 .eq([7, 8, 9]));
2504
2505 let array = Vec::<i32>::new();
2506 let s = Structure::builder("test")
2507 .field_from_iter::<crate::Array, _>("array", &array)
2508 .field_with_static_from_iter::<crate::List, _>(SLIST, &array)
2509 .field_with_id_from_iter::<crate::List, _>(&ilist, &array)
2510 .build();
2511 assert!(s.get::<crate::Array>("array").unwrap().as_ref().is_empty());
2512 assert!(s.get::<crate::List>(SLIST).unwrap().as_ref().is_empty());
2513 assert!(s
2514 .get_by_id::<crate::List>(ilist)
2515 .unwrap()
2516 .as_ref()
2517 .is_empty());
2518 }
2519
2520 #[test]
2521 fn builder_field_if_not_empty() {
2522 crate::init().unwrap();
2523
2524 static SLIST: &GStr = gstr!("slist");
2525 let ilist = idstr!("ilist");
2526 let s = Structure::builder_from_id(idstr!("test"))
2527 .field_if_not_empty::<crate::Array, i32>("array", [1, 2, 3])
2528 .field_with_static_if_not_empty::<crate::List, i32>(SLIST, [4, 5, 6])
2529 .field_with_id_if_not_empty::<crate::List, i32>(&ilist, [7, 8, 9])
2530 .build();
2531 assert!(s
2532 .get::<crate::Array>("array")
2533 .unwrap()
2534 .iter()
2535 .map(|val| val.get::<i32>().unwrap())
2536 .eq([1, 2, 3]));
2537 assert!(s
2538 .get::<crate::List>("slist")
2539 .unwrap()
2540 .iter()
2541 .map(|val| val.get::<i32>().unwrap())
2542 .eq([4, 5, 6]));
2543 assert!(s
2544 .get_by_id::<crate::List>(&ilist)
2545 .unwrap()
2546 .iter()
2547 .map(|val| val.get::<i32>().unwrap())
2548 .eq([7, 8, 9]));
2549
2550 let array = Vec::<i32>::new();
2551 let s = Structure::builder("test")
2552 .field_if_not_empty::<crate::Array, _>("array", &array)
2553 .field_with_static_if_not_empty::<crate::List, _>(SLIST, &array)
2554 .field_with_id_if_not_empty::<crate::List, _>(ilist, &array)
2555 .build();
2556 assert!(!s.has_field("array"));
2557 assert!(!s.has_field("slist"));
2558 assert!(!s.has_field("ilist"));
2559 }
2560
2561 #[test]
2562 fn nth_field_remove_field() {
2563 crate::init().unwrap();
2564
2565 let f3 = idstr!("f3");
2566 let f5 = idstr!("f5");
2567 let f8 = idstr!("f8");
2568 let mut s = Structure::builder("test")
2569 .field("f1", "abc")
2570 .field("f2", "bcd")
2571 .field_with_id(&f3, "cde")
2572 .field("f4", "def")
2573 .field_with_id(&f5, "efg")
2574 .field("f6", "fgh")
2575 .field("f7", "ghi")
2576 .field_with_id(&f8, "hij")
2577 .build();
2578
2579 assert_eq!(s.iter().next().unwrap().0, "f1");
2580 assert_eq!(
2581 s.fields().collect::<Vec<_>>(),
2582 vec!["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"]
2583 );
2584 assert!(s.has_field("f8"));
2585 assert_eq!(s.nth_field_name(7), Some(gstr!("f8")));
2586 assert!(s.nth_field_name(8).is_none());
2587
2588 #[cfg(feature = "v1_26")]
2589 assert_eq!(s.id_iter().next().unwrap().0, "f1");
2590 #[cfg(feature = "v1_26")]
2591 assert_eq!(
2592 s.field_ids().collect::<Vec<_>>(),
2593 vec!["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"]
2594 );
2595 #[cfg(feature = "v1_26")]
2596 assert!(s.has_field_by_id(&f8));
2597 #[cfg(feature = "v1_26")]
2598 assert_eq!(s.nth_field_by_id(7), Some(&f8));
2599 #[cfg(feature = "v1_26")]
2600 assert!(s.nth_field_by_id(8).is_none());
2601
2602 assert_eq!(s.nth_field_name(1), Some(gstr!("f2")));
2603 s.remove_field("f2");
2604 assert_eq!(s.nth_field_name(1), Some(gstr!("f3")));
2605 assert!(s.nth_field_name(7).is_none());
2606 assert_eq!(
2607 s.fields().collect::<Vec<_>>(),
2608 vec!["f1", "f3", "f4", "f5", "f6", "f7", "f8"]
2609 );
2610
2611 assert_eq!(s.nth_field_name(1), Some(gstr!("f3")));
2612 s.remove_field_by_id(&f3);
2613 assert_eq!(s.nth_field_name(1), Some(gstr!("f4")));
2614 assert!(s.nth_field_name(6).is_none());
2615 #[cfg(feature = "v1_26")]
2616 assert_eq!(s.nth_field_by_id(2), Some(&f5));
2617 #[cfg(feature = "v1_26")]
2618 assert!(s.nth_field_by_id(6).is_none());
2619 assert_eq!(
2620 s.fields().collect::<Vec<_>>(),
2621 vec!["f1", "f4", "f5", "f6", "f7", "f8"]
2622 );
2623
2624 s.remove_fields(["f4", "f6"]);
2625 assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f5", "f7", "f8"]);
2626
2627 s.remove_field_by_ids([&f5, &f8]);
2628 assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f7"]);
2629 #[cfg(feature = "v1_26")]
2630 assert_eq!(s.field_ids().collect::<Vec<_>>(), vec!["f1", "f7"]);
2631
2632 s.remove_all_fields();
2633 assert!(s.is_empty());
2634 }
2635
2636 #[cfg(feature = "v1_26")]
2637 #[test]
2638 fn map_in_place() {
2639 crate::init().unwrap();
2640
2641 let f1 = idstr!("f1");
2642 let f2 = idstr!("f2");
2643 let f3 = idstr!("f3");
2644 let mut s = Structure::builder_from_id(idstr!("test"))
2645 .field_with_id(&f1, "abc")
2646 .field_with_id(&f2, "bcd")
2647 .field_with_id(&f3, false)
2648 .build();
2649 assert!(!s.get_by_id::<bool>(&f3).unwrap());
2650
2651 s.map_in_place_by_id(|name, value| {
2652 if *name == f3 {
2653 *value = true.into()
2654 }
2655
2656 std::ops::ControlFlow::Continue(())
2657 });
2658 assert!(s.get_by_id::<bool>(&f3).unwrap());
2659
2660 s.map_in_place_by_id(|name, value| {
2661 match name.as_str() {
2662 "f2" => return std::ops::ControlFlow::Break(()),
2663 "f3" => *value = false.into(),
2664 _ => (),
2665 }
2666 std::ops::ControlFlow::Continue(())
2667 });
2668 assert!(s.get_by_id::<bool>(&f3).unwrap());
2669
2670 s.filter_map_in_place_by_id(|name, value| {
2671 if *name == f3 && value.get::<bool>().unwrap() {
2672 None
2673 } else {
2674 Some(value)
2675 }
2676 });
2677
2678 assert_eq!(s.field_ids().collect::<Vec<_>>(), vec![&f1, &f2]);
2679 }
2680
2681 #[cfg(feature = "v1_28")]
2682 #[test]
2683 fn test_hash() {
2684 crate::init().unwrap();
2685
2686 use std::hash::BuildHasher;
2687 let bh = std::hash::RandomState::new();
2688
2689 let s1 = Structure::builder("test1").build();
2691 let s2 = Structure::builder("test2").build();
2692 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s1));
2693 assert_eq!(bh.hash_one(&s2), bh.hash_one(&s2));
2694 assert_ne!(bh.hash_one(&s1), bh.hash_one(&s2));
2695
2696 let s1 = Structure::builder("test").field("a", 1u32).build();
2698 let s2 = Structure::builder("test").field("b", 1u32).build();
2699 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s1));
2700 assert_eq!(bh.hash_one(&s2), bh.hash_one(&s2));
2701 assert_ne!(bh.hash_one(&s1), bh.hash_one(&s2));
2702
2703 let s1 = Structure::builder("test").field("a", 1u32).build();
2705 let s2 = Structure::builder("test").field("a", 2u32).build();
2706 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s1));
2707 assert_eq!(bh.hash_one(&s2), bh.hash_one(&s2));
2708 assert_ne!(bh.hash_one(&s1), bh.hash_one(&s2));
2709
2710 let s1 = Structure::builder("test")
2712 .field("a", 1u32)
2713 .field("b", 2u32)
2714 .build();
2715 let s2 = Structure::builder("test")
2716 .field("b", 2u32)
2717 .field("a", 1u32)
2718 .build();
2719 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s1));
2720 assert_eq!(bh.hash_one(&s2), bh.hash_one(&s2));
2721 assert_eq!(bh.hash_one(&s1), bh.hash_one(&s2));
2722 }
2723}