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