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