Skip to main content

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