gstreamer/
structure.rs

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