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