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