gstreamer/
structure.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use 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        // Need to make sure to not call ToString::to_string() here, which
230        // we have because of the Display impl. We need StructureRef::to_string()
231        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    // rustdoc-stripper-ignore-next
660    /// Sets field `name` to the given value `value`.
661    ///
662    /// Overrides any default or previously defined value for `name`.
663    #[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    // rustdoc-stripper-ignore-next
670    /// Sets field `name` to the given value `value`.
671    ///
672    /// Overrides any default or previously defined value for `name`.
673    #[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    // rustdoc-stripper-ignore-next
684    /// Sets field `name` to the given value `value`.
685    ///
686    /// Overrides any default or previously defined value for `name`.
687    #[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    // rustdoc-stripper-ignore-next
694    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
695    ///
696    /// This has no effect if the `predicate` evaluates to `false`,
697    /// i.e. default or previous value for `name` is kept.
698    #[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    // rustdoc-stripper-ignore-next
711    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
712    ///
713    /// This has no effect if the `predicate` evaluates to `false`,
714    /// i.e. default or previous value for `name` is kept.
715    #[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    // rustdoc-stripper-ignore-next
728    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
729    ///
730    /// This has no effect if the `predicate` evaluates to `false`,
731    /// i.e. default or previous value for `name` is kept.
732    #[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    // rustdoc-stripper-ignore-next
745    /// Sets field `name` to the given inner value if `value` is `Some`.
746    ///
747    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
748    #[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    // rustdoc-stripper-ignore-next
760    /// Sets field `name` to the given inner value if `value` is `Some`.
761    ///
762    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
763    #[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    // rustdoc-stripper-ignore-next
775    /// Sets field `name` to the given inner value if `value` is `Some`.
776    ///
777    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
778    #[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    // rustdoc-stripper-ignore-next
790    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
791    ///
792    /// Overrides any default or previously defined value for `name`.
793    #[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    // rustdoc-stripper-ignore-next
807    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
808    ///
809    /// Overrides any default or previously defined value for `name`.
810    #[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    // rustdoc-stripper-ignore-next
824    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
825    ///
826    /// Overrides any default or previously defined value for `name`.
827    #[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    // rustdoc-stripper-ignore-next
841    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
842    /// if `iter` is not empty.
843    ///
844    /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
845    #[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    // rustdoc-stripper-ignore-next
862    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
863    /// if `iter` is not empty.
864    ///
865    /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
866    #[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    // rustdoc-stripper-ignore-next
883    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
884    /// if `iter` is not empty.
885    ///
886    /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
887    #[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    // rustdoc-stripper-ignore-next
904    /// Sets field `name` to the given value `value`.
905    ///
906    /// Overrides any default or previously defined value for `name`.
907    #[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    // rustdoc-stripper-ignore-next
917    /// Sets field `name` to the given value `value`.
918    ///
919    /// Overrides any default or previously defined value for `name`.
920    #[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    // rustdoc-stripper-ignore-next
942    /// Sets field `name` to the given value `value`.
943    ///
944    /// Overrides any default or previously defined value for `name`.
945    #[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    // rustdoc-stripper-ignore-next
967    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
968    ///
969    /// This has no effect if the `predicate` evaluates to `false`,
970    /// i.e. default or previous value for `name` is kept.
971    #[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    // rustdoc-stripper-ignore-next
979    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
980    ///
981    /// This has no effect if the `predicate` evaluates to `false`,
982    /// i.e. default or previous value for `name` is kept.
983    #[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    // rustdoc-stripper-ignore-next
996    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
997    ///
998    /// This has no effect if the `predicate` evaluates to `false`,
999    /// i.e. default or previous value for `name` is kept.
1000    #[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    // rustdoc-stripper-ignore-next
1013    /// Sets field `name` to the given inner value if `value` is `Some`.
1014    ///
1015    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
1016    #[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    // rustdoc-stripper-ignore-next
1024    /// Sets field `name` to the given inner value if `value` is `Some`.
1025    ///
1026    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
1027    #[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    // rustdoc-stripper-ignore-next
1039    /// Sets field `name` to the given inner value if `value` is `Some`.
1040    ///
1041    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
1042    #[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    // rustdoc-stripper-ignore-next
1518    /// Executes the provided `func` on each field, possibly modifying the value.
1519    #[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    // rustdoc-stripper-ignore-next
1551    /// Executes the provided `func` on each field with an owned value.
1552    ///
1553    /// * If `func` returns `Some(value)`, the field's value is replaced with
1554    ///   `value`.
1555    /// * If `func` returns `None`, the field is removed.
1556    #[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    // rustdoc-stripper-ignore-next
1594    /// Executes the provided `func` on each field, possibly modifying the value,
1595    /// as long as `ControlFlow::Continue(())` is returned.
1596    ///
1597    /// Using `Quark`s is deprecated, however this method is kept because there
1598    /// are no other means to achieve this pre-GStreamer-1.26. With feature v1_26,
1599    /// use [map_in_place_by_id] instead.
1600    ///
1601    /// # Returns:
1602    ///
1603    /// * `ControlFlow::Continue(())` if `func` returned this for all fields,
1604    /// * `ControlFlow::Break(())` otherwise.
1605    ///
1606    /// [map_in_place_by_id]: crate::StructureRef::map_in_place_by_id
1607    #[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    // rustdoc-stripper-ignore-next
1639    /// Executes the provided `func` on each field with an owned value.
1640    ///
1641    /// * If `func` returns `Some(value)`, the field's value is replaced with
1642    ///   `value`.
1643    /// * If `func` returns `None`, the field is removed.
1644    ///
1645    /// Using `Quark`s is deprecated, however this method is kept because there
1646    /// are no other means to achieve this pre-GStreamer-1.26. With feature v1_26,
1647    /// use [filter_map_in_place_by_id] instead.
1648    ///
1649    /// [filter_map_in_place_by_id]: crate::StructureRef::filter_map_in_place_by_id
1650    #[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// Need gst_value_hash from 1.28
1990#[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        // re-implement gst_hash_structure() so the hashing is not depending on the fields order.
2000        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    // rustdoc-stripper-ignore-next
2049    /// Sets field `name` to the given value `value`.
2050    ///
2051    /// Overrides any default or previously defined value for `name`.
2052    #[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    // rustdoc-stripper-ignore-next
2059    /// Sets field `name` to the given value `value`.
2060    ///
2061    /// Overrides any default or previously defined value for `name`.
2062    #[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    // rustdoc-stripper-ignore-next
2073    /// Sets field `name` to the given value `value`.
2074    ///
2075    /// Overrides any default or previously defined value for `name`.
2076    #[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        // Different names
2572        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        // Same name different fields
2579        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        // Same name different field values
2586        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        // Same structure but fields in a different order
2593        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}