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
605        &mut *(ptr as *mut StructureRef)
606    }
607
608    #[inline]
609    pub fn as_ptr(&self) -> *const ffi::GstStructure {
610        self as *const Self as *const ffi::GstStructure
611    }
612
613    #[inline]
614    pub fn as_mut_ptr(&self) -> *mut ffi::GstStructure {
615        self as *const Self as *mut ffi::GstStructure
616    }
617
618    #[doc(alias = "gst_structure_get")]
619    pub fn get<'a, T: FromValue<'a>>(
620        &'a self,
621        name: impl IntoGStr,
622    ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
623    {
624        name.run_with_gstr(|name| {
625            self.value(name)
626                .map_err(|err| match err {
627                    GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
628                    _ => unreachable!(),
629                })?
630                .get()
631                .map_err(|err| GetError::from_value_get_error(IdStr::from(name), err))
632        })
633    }
634
635    #[doc(alias = "gst_structure_id_str_get")]
636    #[inline]
637    pub fn get_by_id<'a, T: FromValue<'a>>(
638        &'a self,
639        name: impl AsRef<IdStr>,
640    ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
641    {
642        self.value_by_id(name.as_ref())
643            .map_err(|err| match err {
644                GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
645                _ => unreachable!(),
646            })?
647            .get()
648            .map_err(|err| GetError::from_value_get_error(name, err))
649    }
650
651    #[doc(alias = "gst_structure_get")]
652    pub fn get_optional<'a, T: FromValue<'a>>(
653        &'a self,
654        name: impl IntoGStr,
655    ) -> Result<
656        Option<T>,
657        GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
658    > {
659        name.run_with_gstr(|name| {
660            self.value(name)
661                .ok()
662                .map(|v| v.get())
663                .transpose()
664                .map_err(|err| GetError::from_value_get_error(IdStr::from(name), err))
665        })
666    }
667
668    #[doc(alias = "gst_structure_id_str_get")]
669    pub fn get_optional_by_id<'a, T: FromValue<'a>>(
670        &'a self,
671        name: impl AsRef<IdStr>,
672    ) -> Result<
673        Option<T>,
674        GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
675    > {
676        self.value_by_id(name.as_ref())
677            .ok()
678            .map(|v| v.get())
679            .transpose()
680            .map_err(|err| GetError::from_value_get_error(name, err))
681    }
682
683    #[doc(alias = "get_value")]
684    #[doc(alias = "gst_structure_get_value")]
685    pub fn value(
686        &self,
687        name: impl IntoGStr,
688    ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
689        unsafe {
690            name.run_with_gstr(|name| {
691                let value = ffi::gst_structure_get_value(&self.0, name.as_ptr());
692
693                if value.is_null() {
694                    return Err(GetError::new_field_not_found(IdStr::from(name)));
695                }
696
697                Ok(&*(value as *const SendValue))
698            })
699        }
700    }
701
702    #[doc(alias = "gst_structure_id_str_get_value")]
703    pub fn value_by_id(
704        &self,
705        name: impl AsRef<IdStr>,
706    ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
707        unsafe {
708            cfg_if! {
709                if #[cfg(feature = "v1_26")] {
710                    let value = ffi::gst_structure_id_str_get_value(&self.0, name.as_ref().as_ptr());
711                } else {
712                    let value = ffi::gst_structure_get_value(&self.0, name.as_ref().as_gstr().as_ptr());
713                }
714            }
715
716            if value.is_null() {
717                return Err(GetError::new_field_not_found(name));
718            }
719
720            Ok(&*(value as *const SendValue))
721        }
722    }
723
724    #[deprecated = "use `get_by_id()` instead"]
725    #[allow(deprecated)]
726    #[doc(alias = "gst_structure_id_get")]
727    pub fn get_by_quark<'a, T: FromValue<'a>>(
728        &'a self,
729        name: glib::Quark,
730    ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
731    {
732        self.value_by_quark(name)
733            .map_err(|err| match err {
734                GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
735                _ => unreachable!(),
736            })?
737            .get()
738            .map_err(|err| GetError::from_value_get_error(IdStr::from(name.as_str()), err))
739    }
740
741    #[deprecated = "use `get_optional_by_id()` instead"]
742    #[allow(deprecated)]
743    #[doc(alias = "gst_structure_id_get")]
744    pub fn get_optional_by_quark<'a, T: FromValue<'a>>(
745        &'a self,
746        name: glib::Quark,
747    ) -> Result<
748        Option<T>,
749        GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
750    > {
751        self.value_by_quark(name)
752            .ok()
753            .map(|v| v.get())
754            .transpose()
755            .map_err(|err| GetError::from_value_get_error(IdStr::from(name.as_str()), err))
756    }
757
758    #[deprecated = "use `value_by_id()` instead"]
759    #[doc(alias = "gst_structure_id_get_value")]
760    pub fn value_by_quark(
761        &self,
762        name: glib::Quark,
763    ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
764        unsafe {
765            let value = ffi::gst_structure_id_get_value(&self.0, name.into_glib());
766
767            if value.is_null() {
768                return Err(GetError::new_field_not_found(IdStr::from(name.as_str())));
769            }
770
771            Ok(&*(value as *const SendValue))
772        }
773    }
774
775    // rustdoc-stripper-ignore-next
776    /// Sets field `name` to the given value `value`.
777    ///
778    /// Overrides any default or previously defined value for `name`.
779    #[doc(alias = "gst_structure_set")]
780    pub fn set(&mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) {
781        let value = glib::SendValue::from_owned(value);
782        self.set_value(name, value);
783    }
784
785    // rustdoc-stripper-ignore-next
786    /// Sets field `name` to the given value `value`.
787    ///
788    /// Overrides any default or previously defined value for `name`.
789    #[doc(alias = "gst_structure_set_static_str")]
790    pub fn set_with_static(
791        &mut self,
792        name: impl AsRef<GStr> + 'static,
793        value: impl Into<glib::Value> + Send,
794    ) {
795        let value = glib::SendValue::from_owned(value);
796        self.set_value_with_static(name, value);
797    }
798
799    // rustdoc-stripper-ignore-next
800    /// Sets field `name` to the given value `value`.
801    ///
802    /// Overrides any default or previously defined value for `name`.
803    #[doc(alias = "gst_structure_id_str_set")]
804    pub fn set_with_id(&mut self, name: impl AsRef<IdStr>, value: impl Into<glib::Value> + Send) {
805        let value = glib::SendValue::from_owned(value);
806        self.set_value_with_id(name, value);
807    }
808
809    // rustdoc-stripper-ignore-next
810    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
811    ///
812    /// This has no effect if the `predicate` evaluates to `false`,
813    /// i.e. default or previous value for `name` is kept.
814    #[doc(alias = "gst_structure_set")]
815    pub fn set_if(
816        &mut self,
817        name: impl IntoGStr,
818        value: impl Into<glib::Value> + Send,
819        predicate: bool,
820    ) {
821        if predicate {
822            self.set(name, value);
823        }
824    }
825
826    // rustdoc-stripper-ignore-next
827    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
828    ///
829    /// This has no effect if the `predicate` evaluates to `false`,
830    /// i.e. default or previous value for `name` is kept.
831    #[doc(alias = "gst_structure_set_static_str")]
832    pub fn set_with_static_if(
833        &mut self,
834        name: impl AsRef<GStr> + 'static,
835        value: impl Into<glib::Value> + Send,
836        predicate: bool,
837    ) {
838        if predicate {
839            self.set_with_static(name, value);
840        }
841    }
842
843    // rustdoc-stripper-ignore-next
844    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
845    ///
846    /// This has no effect if the `predicate` evaluates to `false`,
847    /// i.e. default or previous value for `name` is kept.
848    #[doc(alias = "gst_structure_id_str_set")]
849    pub fn set_with_id_if(
850        &mut self,
851        name: impl AsRef<IdStr>,
852        value: impl Into<glib::Value> + Send,
853        predicate: bool,
854    ) {
855        if predicate {
856            self.set_with_id(name, value);
857        }
858    }
859
860    // rustdoc-stripper-ignore-next
861    /// Sets field `name` to the given inner value if `value` is `Some`.
862    ///
863    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
864    #[doc(alias = "gst_structure_set")]
865    pub fn set_if_some(
866        &mut self,
867        name: impl IntoGStr,
868        value: Option<impl Into<glib::Value> + Send>,
869    ) {
870        if let Some(value) = value {
871            self.set(name, value);
872        }
873    }
874
875    // rustdoc-stripper-ignore-next
876    /// Sets field `name` to the given inner value if `value` is `Some`.
877    ///
878    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
879    #[doc(alias = "gst_structure_set_static_str")]
880    pub fn set_with_static_if_some(
881        &mut self,
882        name: impl AsRef<GStr> + 'static,
883        value: Option<impl Into<glib::Value> + Send>,
884    ) {
885        if let Some(value) = value {
886            self.set_with_static(name, value);
887        }
888    }
889
890    // rustdoc-stripper-ignore-next
891    /// Sets field `name` to the given inner value if `value` is `Some`.
892    ///
893    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
894    #[doc(alias = "gst_structure_id_str_set")]
895    pub fn set_with_id_if_some(
896        &mut self,
897        name: impl AsRef<IdStr>,
898        value: Option<impl Into<glib::Value> + Send>,
899    ) {
900        if let Some(value) = value {
901            self.set_with_id(name, value);
902        }
903    }
904
905    // rustdoc-stripper-ignore-next
906    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
907    ///
908    /// Overrides any default or previously defined value for `name`.
909    #[inline]
910    pub fn set_from_iter<
911        V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
912        I: ToSendValue,
913    >(
914        &mut self,
915        name: impl IntoGStr,
916        iter: impl IntoIterator<Item = I>,
917    ) {
918        let iter = iter.into_iter().map(|item| item.to_send_value());
919        self.set(name, V::from_iter(iter));
920    }
921
922    // rustdoc-stripper-ignore-next
923    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
924    ///
925    /// Overrides any default or previously defined value for `name`.
926    #[inline]
927    pub fn set_with_static_from_iter<
928        V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
929        I: ToSendValue,
930    >(
931        &mut self,
932        name: impl AsRef<GStr> + 'static,
933        iter: impl IntoIterator<Item = I>,
934    ) {
935        let iter = iter.into_iter().map(|item| item.to_send_value());
936        self.set_with_static(name, V::from_iter(iter));
937    }
938
939    // rustdoc-stripper-ignore-next
940    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s the `Item`s.
941    ///
942    /// Overrides any default or previously defined value for `name`.
943    #[inline]
944    pub fn set_with_id_from_iter<
945        V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
946        I: ToSendValue,
947    >(
948        &mut self,
949        name: impl AsRef<IdStr>,
950        iter: impl IntoIterator<Item = I>,
951    ) {
952        let iter = iter.into_iter().map(|item| item.to_send_value());
953        self.set_with_id(name, V::from_iter(iter));
954    }
955
956    // rustdoc-stripper-ignore-next
957    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
958    /// if `iter` is not empty.
959    ///
960    /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
961    #[inline]
962    pub fn set_if_not_empty<
963        V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
964        I: ToSendValue,
965    >(
966        &mut self,
967        name: impl IntoGStr,
968        iter: impl IntoIterator<Item = I>,
969    ) {
970        let mut iter = iter.into_iter().peekable();
971        if iter.peek().is_some() {
972            let iter = iter.map(|item| item.to_send_value());
973            self.set(name, V::from_iter(iter));
974        }
975    }
976
977    // rustdoc-stripper-ignore-next
978    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
979    /// if `iter` is not empty.
980    ///
981    /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
982    #[inline]
983    pub fn set_with_static_if_not_empty<
984        V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
985        I: ToSendValue,
986    >(
987        &mut self,
988        name: impl AsRef<GStr> + 'static,
989        iter: impl IntoIterator<Item = I>,
990    ) {
991        let mut iter = iter.into_iter().peekable();
992        if iter.peek().is_some() {
993            let iter = iter.map(|item| item.to_send_value());
994            self.set_with_static(name, V::from_iter(iter));
995        }
996    }
997
998    // rustdoc-stripper-ignore-next
999    /// Sets field `name` using the given `ValueType` `V` built from `iter`'s Item`s,
1000    /// if `iter` is not empty.
1001    ///
1002    /// This has no effect if `iter` is empty, i.e. previous value for `name` is unchanged.
1003    #[inline]
1004    pub fn set_with_id_if_not_empty<
1005        V: ValueType + Into<Value> + FromIterator<SendValue> + Send,
1006        I: ToSendValue,
1007    >(
1008        &mut self,
1009        name: impl AsRef<IdStr>,
1010        iter: impl IntoIterator<Item = I>,
1011    ) {
1012        let mut iter = iter.into_iter().peekable();
1013        if iter.peek().is_some() {
1014            let iter = iter.map(|item| item.to_send_value());
1015            self.set_with_id(name, V::from_iter(iter));
1016        }
1017    }
1018
1019    // rustdoc-stripper-ignore-next
1020    /// Sets field `name` to the given value `value`.
1021    ///
1022    /// Overrides any default or previously defined value for `name`.
1023    #[doc(alias = "gst_structure_set_value")]
1024    pub fn set_value(&mut self, name: impl IntoGStr, value: SendValue) {
1025        unsafe {
1026            name.run_with_gstr(|name| {
1027                ffi::gst_structure_take_value(&mut self.0, name.as_ptr(), &mut value.into_raw())
1028            });
1029        }
1030    }
1031
1032    // rustdoc-stripper-ignore-next
1033    /// Sets field `name` to the given value `value`.
1034    ///
1035    /// Overrides any default or previously defined value for `name`.
1036    #[doc(alias = "gst_structure_set_value_static_str")]
1037    pub fn set_value_with_static(&mut self, name: impl AsRef<GStr> + 'static, value: SendValue) {
1038        unsafe {
1039            cfg_if! {
1040                if #[cfg(feature = "v1_26")] {
1041                    ffi::gst_structure_take_value_static_str(
1042                        &mut self.0,
1043                        name.as_ref().as_ptr(),
1044                        &mut value.into_raw(),
1045                    )
1046                } else {
1047                    ffi::gst_structure_take_value(
1048                        &mut self.0,
1049                        name.as_ref().as_ptr(),
1050                        &mut value.into_raw(),
1051                    )
1052                }
1053            }
1054        }
1055    }
1056
1057    // rustdoc-stripper-ignore-next
1058    /// Sets field `name` to the given value `value`.
1059    ///
1060    /// Overrides any default or previously defined value for `name`.
1061    #[doc(alias = "gst_structure_id_str_set_value")]
1062    pub fn set_value_with_id(&mut self, name: impl AsRef<IdStr>, value: SendValue) {
1063        unsafe {
1064            cfg_if! {
1065                if #[cfg(feature = "v1_26")] {
1066                    ffi::gst_structure_id_str_take_value(
1067                        &mut self.0,
1068                        name.as_ref().as_ptr(),
1069                        &mut value.into_raw(),
1070                    )
1071                } else {
1072                    ffi::gst_structure_take_value(
1073                        &mut self.0,
1074                        name.as_ref().as_gstr().as_ptr(),
1075                        &mut value.into_raw(),
1076                    )
1077                }
1078            }
1079        }
1080    }
1081
1082    // rustdoc-stripper-ignore-next
1083    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
1084    ///
1085    /// This has no effect if the `predicate` evaluates to `false`,
1086    /// i.e. default or previous value for `name` is kept.
1087    #[doc(alias = "gst_structure_set_value")]
1088    pub fn set_value_if(&mut self, name: impl IntoGStr, value: SendValue, predicate: bool) {
1089        if predicate {
1090            self.set_value(name, value);
1091        }
1092    }
1093
1094    // rustdoc-stripper-ignore-next
1095    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
1096    ///
1097    /// This has no effect if the `predicate` evaluates to `false`,
1098    /// i.e. default or previous value for `name` is kept.
1099    #[doc(alias = "gst_structure_set_value_static_str")]
1100    pub fn set_value_with_static_if(
1101        &mut self,
1102        name: impl AsRef<GStr> + 'static,
1103        value: SendValue,
1104        predicate: bool,
1105    ) {
1106        if predicate {
1107            self.set_value_with_static(name, value);
1108        }
1109    }
1110
1111    // rustdoc-stripper-ignore-next
1112    /// Sets field `name` to the given `value` if the `predicate` evaluates to `true`.
1113    ///
1114    /// This has no effect if the `predicate` evaluates to `false`,
1115    /// i.e. default or previous value for `name` is kept.
1116    #[doc(alias = "gst_structure_id_str_set_value")]
1117    pub fn set_value_with_id_if(
1118        &mut self,
1119        name: impl AsRef<IdStr>,
1120        value: SendValue,
1121        predicate: bool,
1122    ) {
1123        if predicate {
1124            self.set_value_with_id(name, value);
1125        }
1126    }
1127
1128    // rustdoc-stripper-ignore-next
1129    /// Sets field `name` to the given inner value if `value` is `Some`.
1130    ///
1131    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
1132    #[doc(alias = "gst_structure_set_value")]
1133    pub fn set_value_if_some(&mut self, name: impl IntoGStr, value: Option<SendValue>) {
1134        if let Some(value) = value {
1135            self.set_value(name, value);
1136        }
1137    }
1138
1139    // rustdoc-stripper-ignore-next
1140    /// Sets field `name` to the given inner value if `value` is `Some`.
1141    ///
1142    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
1143    #[doc(alias = "gst_structure_set_value_static_str")]
1144    pub fn set_value_with_static_if_some(
1145        &mut self,
1146        name: impl AsRef<GStr> + 'static,
1147        value: Option<SendValue>,
1148    ) {
1149        if let Some(value) = value {
1150            self.set_value_with_static(name, value);
1151        }
1152    }
1153
1154    // rustdoc-stripper-ignore-next
1155    /// Sets field `name` to the given inner value if `value` is `Some`.
1156    ///
1157    /// This has no effect if the value is `None`, i.e. default or previous value for `name` is kept.
1158    #[doc(alias = "gst_structure_id_str_set_value")]
1159    pub fn set_value_with_id_if_some(&mut self, name: impl AsRef<IdStr>, value: Option<SendValue>) {
1160        if let Some(value) = value {
1161            self.set_value_with_id(name, value);
1162        }
1163    }
1164
1165    #[deprecated = "use `set_by_id()` instead"]
1166    #[allow(deprecated)]
1167    #[doc(alias = "gst_structure_id_set")]
1168    pub fn set_by_quark(&mut self, name: glib::Quark, value: impl Into<glib::Value> + Send) {
1169        let value = glib::SendValue::from_owned(value);
1170        self.set_value_by_quark(name, value);
1171    }
1172
1173    #[deprecated = "use `set_by_id_if_some()` instead"]
1174    #[allow(deprecated)]
1175    #[doc(alias = "gst_structure_id_set")]
1176    pub fn set_by_quark_if_some(
1177        &mut self,
1178        name: glib::Quark,
1179        value: Option<impl Into<glib::Value> + Send>,
1180    ) {
1181        if let Some(value) = value {
1182            self.set_by_quark(name, value);
1183        }
1184    }
1185
1186    #[deprecated = "use `set_by_id_value()` instead"]
1187    #[doc(alias = "gst_structure_id_set_value")]
1188    pub fn set_value_by_quark(&mut self, name: glib::Quark, value: SendValue) {
1189        unsafe {
1190            ffi::gst_structure_id_take_value(&mut self.0, name.into_glib(), &mut value.into_raw());
1191        }
1192    }
1193
1194    #[deprecated = "use `set_by_id_value_if_some()` instead"]
1195    #[allow(deprecated)]
1196    #[doc(alias = "gst_structure_id_set_value")]
1197    pub fn set_value_by_quark_if_some(&mut self, name: glib::Quark, value: Option<SendValue>) {
1198        if let Some(value) = value {
1199            self.set_value_by_quark(name, value);
1200        }
1201    }
1202
1203    #[doc(alias = "get_name")]
1204    #[doc(alias = "gst_structure_get_name")]
1205    pub fn name(&self) -> &glib::GStr {
1206        unsafe { glib::GStr::from_ptr(ffi::gst_structure_get_name(&self.0)) }
1207    }
1208
1209    #[cfg(feature = "v1_26")]
1210    #[doc(alias = "get_name")]
1211    #[doc(alias = "gst_structure_get_name_id_str")]
1212    pub fn name_id(&self) -> &IdStr {
1213        unsafe { &*(ffi::gst_structure_get_name_id_str(&self.0) as *const crate::IdStr) }
1214    }
1215
1216    #[deprecated = "use `name()` instead, or `name_id()` with feature v1_26"]
1217    #[doc(alias = "gst_structure_get_name_id")]
1218    pub fn name_quark(&self) -> glib::Quark {
1219        unsafe { from_glib(ffi::gst_structure_get_name_id(&self.0)) }
1220    }
1221
1222    #[doc(alias = "gst_structure_set_name")]
1223    pub fn set_name(&mut self, name: impl IntoGStr) {
1224        unsafe {
1225            name.run_with_gstr(|name| ffi::gst_structure_set_name(&mut self.0, name.as_ptr()))
1226        }
1227    }
1228
1229    #[doc(alias = "gst_structure_set_name_static_str")]
1230    pub fn set_name_from_static(&mut self, name: impl AsRef<GStr> + 'static) {
1231        unsafe {
1232            cfg_if! {
1233                if #[cfg(feature = "v1_26")] {
1234                    ffi::gst_structure_set_name_static_str(
1235                        &mut self.0,
1236                        name.as_ref().as_ptr(),
1237                    )
1238                } else {
1239                    ffi::gst_structure_set_name(&mut self.0, name.as_ref().as_ptr())
1240                }
1241            }
1242        }
1243    }
1244
1245    #[doc(alias = "gst_structure_set_name_id_str")]
1246    pub fn set_name_from_id(&mut self, name: impl AsRef<IdStr>) {
1247        unsafe {
1248            cfg_if! {
1249                if #[cfg(feature = "v1_26")] {
1250                    ffi::gst_structure_set_name_id_str(
1251                        &mut self.0,
1252                        name.as_ref().as_ptr(),
1253                    )
1254                } else {
1255                    ffi::gst_structure_set_name(&mut self.0, name.as_ref().as_gstr().as_ptr())
1256                }
1257            }
1258        }
1259    }
1260
1261    #[doc(alias = "gst_structure_set_name")]
1262    pub fn set_name_if_some(&mut self, name: Option<impl IntoGStr>) {
1263        if let Some(name) = name {
1264            self.set_name(name);
1265        }
1266    }
1267
1268    #[doc(alias = "gst_structure_set_name_static_str")]
1269    pub fn set_name_from_static_if_some(&mut self, name: Option<impl AsRef<GStr> + 'static>) {
1270        if let Some(name) = name {
1271            self.set_name_from_static(name);
1272        }
1273    }
1274
1275    #[doc(alias = "gst_structure_set_name_id_str")]
1276    pub fn set_name_from_id_if_some(&mut self, name: Option<impl AsRef<IdStr>>) {
1277        if let Some(name) = name {
1278            self.set_name_from_id(name);
1279        }
1280    }
1281
1282    #[doc(alias = "gst_structure_has_name")]
1283    pub fn has_name(&self, name: &str) -> bool {
1284        self.name() == name
1285    }
1286
1287    #[doc(alias = "gst_structure_has_field")]
1288    pub fn has_field(&self, field: impl IntoGStr) -> bool {
1289        unsafe {
1290            field.run_with_gstr(|field| {
1291                from_glib(ffi::gst_structure_has_field(&self.0, field.as_ptr()))
1292            })
1293        }
1294    }
1295
1296    #[doc(alias = "gst_structure_id_str_has_field")]
1297    pub fn has_field_by_id(&self, field: impl AsRef<IdStr>) -> bool {
1298        unsafe {
1299            cfg_if! {
1300                if #[cfg(feature = "v1_26")] {
1301                    from_glib(ffi::gst_structure_id_str_has_field(
1302                        &self.0,
1303                        field.as_ref().as_ptr(),
1304                    ))
1305                } else {
1306                    from_glib(ffi::gst_structure_has_field(
1307                        &self.0,
1308                        field.as_ref().as_gstr().as_ptr(),
1309                    ))
1310                }
1311            }
1312        }
1313    }
1314
1315    #[doc(alias = "gst_structure_has_field_typed")]
1316    pub fn has_field_with_type(&self, field: impl IntoGStr, type_: glib::Type) -> bool {
1317        unsafe {
1318            field.run_with_gstr(|field| {
1319                from_glib(ffi::gst_structure_has_field_typed(
1320                    &self.0,
1321                    field.as_ptr(),
1322                    type_.into_glib(),
1323                ))
1324            })
1325        }
1326    }
1327
1328    #[doc(alias = "gst_structure_id_str_has_field_typed")]
1329    pub fn has_field_with_type_by_id(&self, field: impl AsRef<IdStr>, type_: glib::Type) -> bool {
1330        unsafe {
1331            cfg_if! {
1332                if #[cfg(feature = "v1_26")] {
1333                    from_glib(ffi::gst_structure_id_str_has_field_typed(
1334                        &self.0,
1335                        field.as_ref().as_ptr(),
1336                        type_.into_glib(),
1337                    ))
1338                } else {
1339                    from_glib(ffi::gst_structure_has_field_typed(
1340                        &self.0,
1341                        field.as_ref().as_gstr().as_ptr(),
1342                        type_.into_glib(),
1343                    ))
1344                }
1345            }
1346        }
1347    }
1348
1349    #[deprecated = "use `has_field_by_id()`"]
1350    #[doc(alias = "gst_structure_id_has_field")]
1351    pub fn has_field_by_quark(&self, field: glib::Quark) -> bool {
1352        unsafe { from_glib(ffi::gst_structure_id_has_field(&self.0, field.into_glib())) }
1353    }
1354
1355    #[deprecated = "use `has_field_with_type_by_id()`"]
1356    #[doc(alias = "gst_structure_id_has_field_typed")]
1357    pub fn has_field_with_type_by_quark(&self, field: glib::Quark, type_: glib::Type) -> bool {
1358        unsafe {
1359            from_glib(ffi::gst_structure_id_has_field_typed(
1360                &self.0,
1361                field.into_glib(),
1362                type_.into_glib(),
1363            ))
1364        }
1365    }
1366
1367    #[doc(alias = "gst_structure_remove_field")]
1368    pub fn remove_field(&mut self, field: impl IntoGStr) {
1369        unsafe {
1370            field.run_with_gstr(|field| {
1371                ffi::gst_structure_remove_field(&mut self.0, field.as_ptr())
1372            });
1373        }
1374    }
1375
1376    #[doc(alias = "gst_structure_remove_fields")]
1377    pub fn remove_fields<S: IntoGStr>(&mut self, fields: impl IntoIterator<Item = S>) {
1378        for f in fields.into_iter() {
1379            self.remove_field(f)
1380        }
1381    }
1382
1383    #[doc(alias = "gst_structure_id_str_remove_field")]
1384    pub fn remove_field_by_id(&mut self, field: impl AsRef<IdStr>) {
1385        unsafe {
1386            cfg_if! {
1387                if #[cfg(feature = "v1_26")] {
1388                    ffi::gst_structure_id_str_remove_field(&mut self.0, field.as_ref().as_ptr())
1389                } else {
1390                    ffi::gst_structure_remove_field(&mut self.0, field.as_ref().as_gstr().as_ptr())
1391                }
1392            }
1393        }
1394    }
1395
1396    #[doc(alias = "gst_structure_id_str_remove_fields")]
1397    pub fn remove_field_by_ids<S: AsRef<IdStr>>(&mut self, fields: impl IntoIterator<Item = S>) {
1398        for f in fields.into_iter() {
1399            self.remove_field_by_id(f)
1400        }
1401    }
1402
1403    #[doc(alias = "gst_structure_remove_all_fields")]
1404    pub fn remove_all_fields(&mut self) {
1405        unsafe {
1406            ffi::gst_structure_remove_all_fields(&mut self.0);
1407        }
1408    }
1409
1410    pub fn fields(&self) -> FieldIterator {
1411        FieldIterator::new(self)
1412    }
1413
1414    pub fn iter(&self) -> Iter {
1415        Iter::new(self)
1416    }
1417
1418    #[cfg(feature = "v1_26")]
1419    pub fn field_ids(&self) -> FieldIdIterator {
1420        FieldIdIterator::new(self)
1421    }
1422
1423    #[cfg(feature = "v1_26")]
1424    pub fn id_iter(&self) -> IdIter {
1425        IdIter::new(self)
1426    }
1427
1428    #[doc(alias = "get_nth_field_name")]
1429    #[doc(alias = "gst_structure_nth_field_name")]
1430    pub fn nth_field_name(&self, idx: usize) -> Option<&glib::GStr> {
1431        if idx >= self.n_fields() {
1432            return None;
1433        }
1434
1435        unsafe {
1436            let field_name = ffi::gst_structure_nth_field_name(&self.0, idx as u32);
1437            debug_assert!(!field_name.is_null());
1438
1439            Some(glib::GStr::from_ptr(field_name))
1440        }
1441    }
1442
1443    #[cfg(feature = "v1_26")]
1444    #[doc(alias = "get_nth_field_name")]
1445    #[doc(alias = "gst_structure_id_str_nth_field_name")]
1446    pub fn nth_field_by_id(&self, idx: usize) -> Option<&IdStr> {
1447        if idx >= self.n_fields() {
1448            return None;
1449        }
1450
1451        unsafe {
1452            let field_name = ffi::gst_structure_id_str_nth_field_name(&self.0, idx as u32);
1453            debug_assert!(!field_name.is_null());
1454
1455            Some(&*(field_name as *const crate::IdStr))
1456        }
1457    }
1458
1459    #[doc(alias = "gst_structure_n_fields")]
1460    pub fn n_fields(&self) -> usize {
1461        unsafe { ffi::gst_structure_n_fields(&self.0) as usize }
1462    }
1463
1464    pub fn len(&self) -> usize {
1465        self.n_fields()
1466    }
1467
1468    pub fn is_empty(&self) -> bool {
1469        self.n_fields() == 0
1470    }
1471
1472    #[doc(alias = "gst_structure_can_intersect")]
1473    pub fn can_intersect(&self, other: &StructureRef) -> bool {
1474        unsafe { from_glib(ffi::gst_structure_can_intersect(&self.0, &other.0)) }
1475    }
1476
1477    #[doc(alias = "gst_structure_intersect")]
1478    pub fn intersect(&self, other: &StructureRef) -> Option<Structure> {
1479        unsafe { from_glib_full(ffi::gst_structure_intersect(&self.0, &other.0)) }
1480    }
1481
1482    #[doc(alias = "gst_structure_is_subset")]
1483    pub fn is_subset(&self, superset: &StructureRef) -> bool {
1484        unsafe { from_glib(ffi::gst_structure_is_subset(&self.0, &superset.0)) }
1485    }
1486
1487    #[doc(alias = "gst_structure_fixate")]
1488    pub fn fixate(&mut self) {
1489        unsafe { ffi::gst_structure_fixate(&mut self.0) }
1490    }
1491
1492    #[doc(alias = "gst_structure_fixate_field")]
1493    pub fn fixate_field(&mut self, name: impl IntoGStr) -> bool {
1494        unsafe {
1495            name.run_with_gstr(|name| {
1496                from_glib(ffi::gst_structure_fixate_field(&mut self.0, name.as_ptr()))
1497            })
1498        }
1499    }
1500
1501    #[doc(alias = "gst_structure_fixate_field_boolean")]
1502    pub fn fixate_field_bool(&mut self, name: impl IntoGStr, target: bool) -> bool {
1503        unsafe {
1504            name.run_with_gstr(|name| {
1505                from_glib(ffi::gst_structure_fixate_field_boolean(
1506                    &mut self.0,
1507                    name.as_ptr(),
1508                    target.into_glib(),
1509                ))
1510            })
1511        }
1512    }
1513
1514    #[doc(alias = "gst_structure_fixate_field_string")]
1515    pub fn fixate_field_str(&mut self, name: impl IntoGStr, target: impl IntoGStr) -> bool {
1516        unsafe {
1517            name.run_with_gstr(|name| {
1518                target.run_with_gstr(|target| {
1519                    from_glib(ffi::gst_structure_fixate_field_string(
1520                        &mut self.0,
1521                        name.as_ptr(),
1522                        target.as_ptr(),
1523                    ))
1524                })
1525            })
1526        }
1527    }
1528
1529    #[doc(alias = "gst_structure_fixate_field_nearest_double")]
1530    pub fn fixate_field_nearest_double(&mut self, name: impl IntoGStr, target: f64) -> bool {
1531        unsafe {
1532            name.run_with_gstr(|name| {
1533                from_glib(ffi::gst_structure_fixate_field_nearest_double(
1534                    &mut self.0,
1535                    name.as_ptr(),
1536                    target,
1537                ))
1538            })
1539        }
1540    }
1541
1542    #[doc(alias = "gst_structure_fixate_field_nearest_fraction")]
1543    pub fn fixate_field_nearest_fraction(
1544        &mut self,
1545        name: impl IntoGStr,
1546        target: impl Into<Fraction>,
1547    ) -> bool {
1548        skip_assert_initialized!();
1549
1550        let target = target.into();
1551        unsafe {
1552            name.run_with_gstr(|name| {
1553                from_glib(ffi::gst_structure_fixate_field_nearest_fraction(
1554                    &mut self.0,
1555                    name.as_ptr(),
1556                    target.numer(),
1557                    target.denom(),
1558                ))
1559            })
1560        }
1561    }
1562
1563    #[doc(alias = "gst_structure_fixate_field_nearest_int")]
1564    pub fn fixate_field_nearest_int(&mut self, name: impl IntoGStr, target: i32) -> bool {
1565        unsafe {
1566            name.run_with_gstr(|name| {
1567                from_glib(ffi::gst_structure_fixate_field_nearest_int(
1568                    &mut self.0,
1569                    name.as_ptr(),
1570                    target,
1571                ))
1572            })
1573        }
1574    }
1575
1576    #[cfg(feature = "v1_20")]
1577    #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
1578    #[doc(alias = "gst_structure_serialize")]
1579    pub fn serialize(&self, flags: crate::SerializeFlags) -> glib::GString {
1580        unsafe { from_glib_full(ffi::gst_structure_serialize(&self.0, flags.into_glib())) }
1581    }
1582
1583    #[cfg(feature = "v1_24")]
1584    #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
1585    #[doc(alias = "gst_structure_serialize")]
1586    #[doc(alias = "gst_structure_serialize_full")]
1587    pub fn serialize_strict(
1588        &self,
1589        flags: crate::SerializeFlags,
1590    ) -> Result<glib::GString, glib::BoolError> {
1591        unsafe {
1592            let res = ffi::gst_structure_serialize_full(
1593                &self.0,
1594                flags.into_glib() | ffi::GST_SERIALIZE_FLAG_STRICT,
1595            );
1596            if res.is_null() {
1597                Err(glib::bool_error!("Failed to serialize structure to string"))
1598            } else {
1599                Ok(from_glib_full(res))
1600            }
1601        }
1602    }
1603
1604    #[deprecated = "Use `iter()` instead, or `id_iter()` with feature v1_26"]
1605    #[doc(alias = "gst_structure_foreach")]
1606    pub fn foreach<F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>>(
1607        &self,
1608        mut func: F,
1609    ) -> bool {
1610        unsafe {
1611            unsafe extern "C" fn trampoline<
1612                F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>,
1613            >(
1614                quark: glib::ffi::GQuark,
1615                value: *const glib::gobject_ffi::GValue,
1616                user_data: glib::ffi::gpointer,
1617            ) -> glib::ffi::gboolean {
1618                let func = &mut *(user_data as *mut F);
1619                let res = func(from_glib(quark), &*(value as *const glib::Value));
1620
1621                matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1622            }
1623            let func = &mut func as *mut F;
1624            from_glib(ffi::gst_structure_foreach(
1625                self.as_ptr(),
1626                Some(trampoline::<F>),
1627                func as glib::ffi::gpointer,
1628            ))
1629        }
1630    }
1631
1632    #[cfg(feature = "v1_26")]
1633    // rustdoc-stripper-ignore-next
1634    /// Executes the provided `func` on each field, possibly modifying the value.
1635    #[doc(alias = "gst_structure_map_in_place_id_str")]
1636    pub fn map_in_place_by_id<F: FnMut(&IdStr, &mut glib::Value) -> std::ops::ControlFlow<()>>(
1637        &mut self,
1638        mut func: F,
1639    ) {
1640        unsafe {
1641            unsafe extern "C" fn trampoline<
1642                F: FnMut(&IdStr, &mut glib::Value) -> std::ops::ControlFlow<()>,
1643            >(
1644                fieldname: *const ffi::GstIdStr,
1645                value: *mut glib::gobject_ffi::GValue,
1646                user_data: glib::ffi::gpointer,
1647            ) -> glib::ffi::gboolean {
1648                let func = &mut *(user_data as *mut F);
1649                let res = func(
1650                    &*(fieldname as *const IdStr),
1651                    &mut *(value as *mut glib::Value),
1652                );
1653
1654                matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1655            }
1656            let func = &mut func as *mut F;
1657            let _ = ffi::gst_structure_map_in_place_id_str(
1658                self.as_mut_ptr(),
1659                Some(trampoline::<F>),
1660                func as glib::ffi::gpointer,
1661            );
1662        }
1663    }
1664
1665    #[cfg(feature = "v1_26")]
1666    // rustdoc-stripper-ignore-next
1667    /// Executes the provided `func` on each field with an owned value.
1668    ///
1669    /// * If `func` returns `Some(value)`, the field's value is replaced with
1670    ///   `value`.
1671    /// * If `func` returns `None`, the field is removed.
1672    #[doc(alias = "gst_structure_filter_and_map_in_place_id_str")]
1673    pub fn filter_map_in_place_by_id<F: FnMut(&IdStr, glib::Value) -> Option<glib::Value>>(
1674        &mut self,
1675        mut func: F,
1676    ) {
1677        unsafe {
1678            unsafe extern "C" fn trampoline<
1679                F: FnMut(&IdStr, glib::Value) -> Option<glib::Value>,
1680            >(
1681                fieldname: *const ffi::GstIdStr,
1682                value: *mut glib::gobject_ffi::GValue,
1683                user_data: glib::ffi::gpointer,
1684            ) -> glib::ffi::gboolean {
1685                let func = &mut *(user_data as *mut F);
1686
1687                let v = mem::replace(
1688                    &mut *(value as *mut glib::Value),
1689                    glib::Value::uninitialized(),
1690                );
1691                match func(&*(fieldname as *const IdStr), v) {
1692                    None => glib::ffi::GFALSE,
1693                    Some(v) => {
1694                        *value = v.into_raw();
1695                        glib::ffi::GTRUE
1696                    }
1697                }
1698            }
1699
1700            let func = &mut func as *mut F;
1701            ffi::gst_structure_filter_and_map_in_place_id_str(
1702                self.as_mut_ptr(),
1703                Some(trampoline::<F>),
1704                func as glib::ffi::gpointer,
1705            );
1706        }
1707    }
1708
1709    // rustdoc-stripper-ignore-next
1710    /// Executes the provided `func` on each field, possibly modifying the value,
1711    /// as long as `ControlFlow::Continue(())` is returned.
1712    ///
1713    /// Using `Quark`s is deprecated, however this method is kept because there
1714    /// are no other means to achieve this pre-GStreamer-1.26. With feature v1_26,
1715    /// use [map_in_place_by_id] instead.
1716    ///
1717    /// # Returns:
1718    ///
1719    /// * `ControlFlow::Continue(())` if `func` returned this for all fields,
1720    /// * `ControlFlow::Break(())` otherwise.
1721    ///
1722    /// [map_in_place_by_id]: crate::StructureRef::map_in_place_by_id
1723    #[doc(alias = "gst_structure_map_in_place")]
1724    pub fn map_in_place<F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>>(
1725        &mut self,
1726        mut func: F,
1727    ) -> std::ops::ControlFlow<()> {
1728        unsafe {
1729            unsafe extern "C" fn trampoline<
1730                F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>,
1731            >(
1732                quark: glib::ffi::GQuark,
1733                value: *mut glib::gobject_ffi::GValue,
1734                user_data: glib::ffi::gpointer,
1735            ) -> glib::ffi::gboolean {
1736                let func = &mut *(user_data as *mut F);
1737                let res = func(from_glib(quark), &mut *(value as *mut glib::Value));
1738
1739                matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1740            }
1741            let func = &mut func as *mut F;
1742            if from_glib(ffi::gst_structure_map_in_place(
1743                self.as_mut_ptr(),
1744                Some(trampoline::<F>),
1745                func as glib::ffi::gpointer,
1746            )) {
1747                std::ops::ControlFlow::Continue(())
1748            } else {
1749                std::ops::ControlFlow::Break(())
1750            }
1751        }
1752    }
1753
1754    // rustdoc-stripper-ignore-next
1755    /// Executes the provided `func` on each field with an owned value.
1756    ///
1757    /// * If `func` returns `Some(value)`, the field's value is replaced with
1758    ///   `value`.
1759    /// * If `func` returns `None`, the field is removed.
1760    ///
1761    /// Using `Quark`s is deprecated, however this method is kept because there
1762    /// are no other means to achieve this pre-GStreamer-1.26. With feature v1_26,
1763    /// use [filter_map_in_place_by_id] instead.
1764    ///
1765    /// [filter_map_in_place_by_id]: crate::StructureRef::filter_map_in_place_by_id
1766    #[doc(alias = "gst_structure_filter_and_map_in_place")]
1767    pub fn filter_map_in_place<F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>>(
1768        &mut self,
1769        mut func: F,
1770    ) {
1771        unsafe {
1772            unsafe extern "C" fn trampoline<
1773                F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>,
1774            >(
1775                quark: glib::ffi::GQuark,
1776                value: *mut glib::gobject_ffi::GValue,
1777                user_data: glib::ffi::gpointer,
1778            ) -> glib::ffi::gboolean {
1779                let func = &mut *(user_data as *mut F);
1780
1781                let v = mem::replace(
1782                    &mut *(value as *mut glib::Value),
1783                    glib::Value::uninitialized(),
1784                );
1785                match func(from_glib(quark), v) {
1786                    None => glib::ffi::GFALSE,
1787                    Some(v) => {
1788                        *value = v.into_raw();
1789                        glib::ffi::GTRUE
1790                    }
1791                }
1792            }
1793
1794            let func = &mut func as *mut F;
1795            ffi::gst_structure_filter_and_map_in_place(
1796                self.as_mut_ptr(),
1797                Some(trampoline::<F>),
1798                func as glib::ffi::gpointer,
1799            );
1800        }
1801    }
1802}
1803
1804impl fmt::Display for StructureRef {
1805    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1806        let s = unsafe { glib::GString::from_glib_full(ffi::gst_structure_to_string(&self.0)) };
1807        f.write_str(&s)
1808    }
1809}
1810
1811impl fmt::Debug for StructureRef {
1812    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1813        let mut debug = f.debug_struct(self.name());
1814
1815        for (id, field) in self.iter() {
1816            if field.type_() == Structure::static_type() {
1817                let s = field.get::<Structure>().unwrap();
1818                debug.field(id, &s);
1819            } else if field.type_() == crate::Array::static_type() {
1820                let arr = field.get::<crate::Array>().unwrap();
1821                debug.field(id, &arr);
1822            } else if field.type_() == crate::List::static_type() {
1823                let list = field.get::<crate::List>().unwrap();
1824                debug.field(id, &list);
1825            } else {
1826                debug.field(id, &field);
1827            }
1828        }
1829
1830        debug.finish()
1831    }
1832}
1833
1834impl PartialEq for StructureRef {
1835    #[doc(alias = "gst_structure_is_equal")]
1836    fn eq(&self, other: &StructureRef) -> bool {
1837        unsafe { from_glib(ffi::gst_structure_is_equal(&self.0, &other.0)) }
1838    }
1839}
1840
1841impl Eq for StructureRef {}
1842
1843impl glib::types::StaticType for StructureRef {
1844    #[inline]
1845    fn static_type() -> glib::types::Type {
1846        unsafe { from_glib(ffi::gst_structure_get_type()) }
1847    }
1848}
1849
1850unsafe impl<'a> glib::value::FromValue<'a> for &'a StructureRef {
1851    type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
1852
1853    unsafe fn from_value(value: &'a glib::Value) -> Self {
1854        skip_assert_initialized!();
1855        &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const StructureRef)
1856    }
1857}
1858
1859impl glib::value::ToValue for StructureRef {
1860    fn to_value(&self) -> glib::Value {
1861        let mut value = glib::Value::for_value_type::<Structure>();
1862        unsafe {
1863            glib::gobject_ffi::g_value_set_boxed(
1864                value.to_glib_none_mut().0,
1865                self.as_ptr() as *mut _,
1866            )
1867        }
1868        value
1869    }
1870
1871    fn value_type(&self) -> glib::Type {
1872        Self::static_type()
1873    }
1874}
1875
1876impl glib::value::ToValueOptional for StructureRef {
1877    fn to_value_optional(s: Option<&Self>) -> glib::Value {
1878        skip_assert_initialized!();
1879        let mut value = glib::Value::for_value_type::<Structure>();
1880        unsafe {
1881            glib::gobject_ffi::g_value_set_boxed(
1882                value.to_glib_none_mut().0,
1883                s.map(|s| s.as_ptr()).unwrap_or(ptr::null()) as *mut _,
1884            )
1885        }
1886        value
1887    }
1888}
1889
1890crate::utils::define_fixed_size_iter!(
1891    FieldIterator,
1892    &'a StructureRef,
1893    &'a glib::GStr,
1894    |collection: &StructureRef| collection.n_fields(),
1895    |collection: &StructureRef, idx: usize| unsafe {
1896        let field_name = ffi::gst_structure_nth_field_name(&collection.0, idx as u32);
1897        glib::GStr::from_ptr(field_name)
1898    }
1899);
1900
1901#[cfg(feature = "v1_26")]
1902crate::utils::define_fixed_size_iter!(
1903    FieldIdIterator,
1904    &'a StructureRef,
1905    &'a crate::IdStr,
1906    |collection: &StructureRef| collection.n_fields(),
1907    |collection: &StructureRef, idx: usize| unsafe {
1908        let field_name = ffi::gst_structure_id_str_nth_field_name(&collection.0, idx as u32);
1909        debug_assert!(!field_name.is_null());
1910
1911        &*(field_name as *const crate::IdStr)
1912    }
1913);
1914
1915#[must_use = "iterators are lazy and do nothing unless consumed"]
1916#[derive(Debug)]
1917pub struct Iter<'a> {
1918    iter: FieldIterator<'a>,
1919}
1920
1921impl<'a> Iter<'a> {
1922    fn new(structure: &'a StructureRef) -> Iter<'a> {
1923        skip_assert_initialized!();
1924        Iter {
1925            iter: FieldIterator::new(structure),
1926        }
1927    }
1928}
1929
1930impl<'a> Iterator for Iter<'a> {
1931    type Item = (&'a glib::GStr, &'a SendValue);
1932
1933    fn next(&mut self) -> Option<Self::Item> {
1934        let f = self.iter.next()?;
1935        let v = self.iter.collection.value(f);
1936        Some((f, v.unwrap()))
1937    }
1938
1939    fn size_hint(&self) -> (usize, Option<usize>) {
1940        self.iter.size_hint()
1941    }
1942
1943    fn count(self) -> usize {
1944        self.iter.count()
1945    }
1946
1947    fn nth(&mut self, n: usize) -> Option<Self::Item> {
1948        let f = self.iter.nth(n)?;
1949        let v = self.iter.collection.value(f);
1950        Some((f, v.unwrap()))
1951    }
1952
1953    fn last(self) -> Option<Self::Item> {
1954        let structure = self.iter.collection;
1955        let f = self.iter.last()?;
1956        let v = structure.value(f);
1957        Some((f, v.unwrap()))
1958    }
1959}
1960
1961impl DoubleEndedIterator for Iter<'_> {
1962    fn next_back(&mut self) -> Option<Self::Item> {
1963        let f = self.iter.next_back()?;
1964        let v = self.iter.collection.value(f);
1965        Some((f, v.unwrap()))
1966    }
1967
1968    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1969        let f = self.iter.nth_back(n)?;
1970        let v = self.iter.collection.value(f);
1971        Some((f, v.unwrap()))
1972    }
1973}
1974
1975impl ExactSizeIterator for Iter<'_> {}
1976
1977impl std::iter::FusedIterator for Iter<'_> {}
1978
1979#[cfg(feature = "v1_26")]
1980#[must_use = "iterators are lazy and do nothing unless consumed"]
1981#[derive(Debug)]
1982pub struct IdIter<'a> {
1983    iter: FieldIdIterator<'a>,
1984}
1985
1986#[cfg(feature = "v1_26")]
1987impl<'a> IdIter<'a> {
1988    fn new(structure: &'a StructureRef) -> IdIter<'a> {
1989        skip_assert_initialized!();
1990        IdIter {
1991            iter: FieldIdIterator::new(structure),
1992        }
1993    }
1994}
1995
1996#[cfg(feature = "v1_26")]
1997impl<'a> Iterator for IdIter<'a> {
1998    type Item = (&'a IdStr, &'a SendValue);
1999
2000    fn next(&mut self) -> Option<Self::Item> {
2001        let f = self.iter.next()?;
2002        let v = self.iter.collection.value_by_id(f);
2003        Some((f, v.unwrap()))
2004    }
2005
2006    fn size_hint(&self) -> (usize, Option<usize>) {
2007        self.iter.size_hint()
2008    }
2009
2010    fn count(self) -> usize {
2011        self.iter.count()
2012    }
2013
2014    fn nth(&mut self, n: usize) -> Option<Self::Item> {
2015        let f = self.iter.nth(n)?;
2016        let v = self.iter.collection.value_by_id(f);
2017        Some((f, v.unwrap()))
2018    }
2019
2020    fn last(self) -> Option<Self::Item> {
2021        let structure = self.iter.collection;
2022        let f = self.iter.last()?;
2023        let v = structure.value_by_id(f);
2024        Some((f, v.unwrap()))
2025    }
2026}
2027
2028#[cfg(feature = "v1_26")]
2029impl DoubleEndedIterator for IdIter<'_> {
2030    fn next_back(&mut self) -> Option<Self::Item> {
2031        let f = self.iter.next_back()?;
2032        let v = self.iter.collection.value_by_id(f);
2033        Some((f, v.unwrap()))
2034    }
2035
2036    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
2037        let f = self.iter.nth_back(n)?;
2038        let v = self.iter.collection.value_by_id(f);
2039        Some((f, v.unwrap()))
2040    }
2041}
2042
2043#[cfg(feature = "v1_26")]
2044impl ExactSizeIterator for IdIter<'_> {}
2045#[cfg(feature = "v1_26")]
2046impl std::iter::FusedIterator for IdIter<'_> {}
2047
2048impl<'a> IntoIterator for &'a StructureRef {
2049    type IntoIter = Iter<'a>;
2050    type Item = (&'a glib::GStr, &'a SendValue);
2051
2052    fn into_iter(self) -> Self::IntoIter {
2053        self.iter()
2054    }
2055}
2056
2057impl<'a> std::iter::Extend<(&'a str, SendValue)> for StructureRef {
2058    fn extend<T: IntoIterator<Item = (&'a str, SendValue)>>(&mut self, iter: T) {
2059        iter.into_iter().for_each(|(f, v)| self.set_value(f, v));
2060    }
2061}
2062
2063impl<'a> std::iter::Extend<(&'a glib::GStr, SendValue)> for StructureRef {
2064    fn extend<T: IntoIterator<Item = (&'a glib::GStr, SendValue)>>(&mut self, iter: T) {
2065        iter.into_iter().for_each(|(f, v)| self.set_value(f, v));
2066    }
2067}
2068
2069impl std::iter::Extend<(String, SendValue)> for StructureRef {
2070    fn extend<T: IntoIterator<Item = (String, SendValue)>>(&mut self, iter: T) {
2071        iter.into_iter().for_each(|(f, v)| self.set_value(&f, v));
2072    }
2073}
2074
2075impl std::iter::Extend<(glib::GString, SendValue)> for StructureRef {
2076    fn extend<T: IntoIterator<Item = (glib::GString, SendValue)>>(&mut self, iter: T) {
2077        iter.into_iter().for_each(|(f, v)| self.set_value(&f, v));
2078    }
2079}
2080
2081impl<'a> std::iter::Extend<(&'a IdStr, SendValue)> for StructureRef {
2082    #[allow(deprecated)]
2083    fn extend<T: IntoIterator<Item = (&'a IdStr, SendValue)>>(&mut self, iter: T) {
2084        iter.into_iter()
2085            .for_each(|(f, v)| self.set_value_with_id(f, v));
2086    }
2087}
2088
2089impl std::iter::Extend<(IdStr, SendValue)> for StructureRef {
2090    #[allow(deprecated)]
2091    fn extend<T: IntoIterator<Item = (IdStr, SendValue)>>(&mut self, iter: T) {
2092        iter.into_iter()
2093            .for_each(|(f, v)| self.set_value_with_id(f, v));
2094    }
2095}
2096
2097impl std::iter::Extend<(glib::Quark, SendValue)> for StructureRef {
2098    #[allow(deprecated)]
2099    fn extend<T: IntoIterator<Item = (glib::Quark, SendValue)>>(&mut self, iter: T) {
2100        iter.into_iter()
2101            .for_each(|(f, v)| self.set_value_by_quark(f, v));
2102    }
2103}
2104
2105#[derive(Debug)]
2106#[must_use = "The builder must be built to be used"]
2107pub struct Builder {
2108    s: Structure,
2109}
2110
2111impl Builder {
2112    fn new(name: impl IntoGStr) -> Self {
2113        skip_assert_initialized!();
2114        Builder {
2115            s: Structure::new_empty(name),
2116        }
2117    }
2118
2119    fn from_static(name: impl AsRef<GStr> + 'static) -> Self {
2120        skip_assert_initialized!();
2121        Builder {
2122            s: Structure::new_empty_from_static(name),
2123        }
2124    }
2125
2126    pub fn from_id(name: impl AsRef<IdStr>) -> Builder {
2127        skip_assert_initialized!();
2128        Builder {
2129            s: Structure::new_empty_from_id(name),
2130        }
2131    }
2132
2133    // rustdoc-stripper-ignore-next
2134    /// Sets field `name` to the given value `value`.
2135    ///
2136    /// Overrides any default or previously defined value for `name`.
2137    #[inline]
2138    pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self {
2139        self.s.set(name, value);
2140        self
2141    }
2142
2143    // rustdoc-stripper-ignore-next
2144    /// Sets field `name` to the given value `value`.
2145    ///
2146    /// Overrides any default or previously defined value for `name`.
2147    #[inline]
2148    pub fn field_with_static(
2149        mut self,
2150        name: impl AsRef<GStr> + 'static,
2151        value: impl Into<glib::Value> + Send,
2152    ) -> Self {
2153        self.s.set_with_static(name, value);
2154        self
2155    }
2156
2157    // rustdoc-stripper-ignore-next
2158    /// Sets field `name` to the given value `value`.
2159    ///
2160    /// Overrides any default or previously defined value for `name`.
2161    #[inline]
2162    pub fn field_with_id(
2163        mut self,
2164        name: impl AsRef<IdStr>,
2165        value: impl Into<glib::Value> + Send,
2166    ) -> Self {
2167        self.s.set_with_id(name, value);
2168        self
2169    }
2170
2171    impl_builder_gvalue_extra_setters!(field);
2172
2173    #[must_use = "Building the structure without using it has no effect"]
2174    pub fn build(self) -> Structure {
2175        self.s
2176    }
2177}
2178
2179#[cfg(test)]
2180mod tests {
2181    use super::*;
2182    use glib::gstr;
2183
2184    #[test]
2185    fn new_set_get() {
2186        use glib::{value, Type};
2187
2188        crate::init().unwrap();
2189
2190        let mut s = Structure::new_empty("test");
2191        assert_eq!(s.name(), "test");
2192
2193        s.set("f1", "abc");
2194        s.set("f2", String::from("bcd"));
2195        s.set("f3", 123i32);
2196        s.set("f5", Some("efg"));
2197        s.set("f7", 42i32);
2198
2199        assert_eq!(s.get::<&str>("f1"), Ok("abc"));
2200        assert_eq!(s.get::<Option<&str>>("f2"), Ok(Some("bcd")));
2201        assert_eq!(s.get::<i32>("f3"), Ok(123i32));
2202        assert_eq!(s.get_optional::<&str>("f1"), Ok(Some("abc")));
2203        assert_eq!(s.get_optional::<&str>("f4"), Ok(None));
2204        assert_eq!(s.get_optional::<i32>("f3"), Ok(Some(123i32)));
2205        assert_eq!(s.get_optional::<i32>("f4"), Ok(None));
2206        assert_eq!(s.get::<&str>("f5"), Ok("efg"));
2207        assert_eq!(s.get::<i32>("f7"), Ok(42i32));
2208
2209        assert_eq!(
2210            s.get::<i32>("f2"),
2211            Err(GetError::from_value_get_error(
2212                idstr!("f2"),
2213                value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
2214            ))
2215        );
2216        assert_eq!(
2217            s.get::<bool>("f3"),
2218            Err(GetError::from_value_get_error(
2219                idstr!("f3"),
2220                value::ValueTypeMismatchError::new(Type::I32, Type::BOOL),
2221            ))
2222        );
2223        assert_eq!(
2224            s.get::<&str>("f4"),
2225            Err(GetError::new_field_not_found(idstr!("f4")))
2226        );
2227        assert_eq!(
2228            s.get::<i32>("f4"),
2229            Err(GetError::new_field_not_found(idstr!("f4")))
2230        );
2231
2232        assert_eq!(
2233            s.fields().collect::<Vec<_>>(),
2234            vec!["f1", "f2", "f3", "f5", "f7"]
2235        );
2236
2237        let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>();
2238        assert_eq!(v.len(), 5);
2239        assert_eq!(v[0].0, "f1");
2240        assert_eq!(v[0].1.get::<&str>(), Ok("abc"));
2241        assert_eq!(v[1].0, "f2");
2242        assert_eq!(v[1].1.get::<&str>(), Ok("bcd"));
2243        assert_eq!(v[2].0, "f3");
2244        assert_eq!(v[2].1.get::<i32>(), Ok(123i32));
2245        assert_eq!(v[3].0, "f5");
2246        assert_eq!(v[3].1.get::<&str>(), Ok("efg"));
2247        assert_eq!(v[4].0, "f7");
2248        assert_eq!(v[4].1.get::<i32>(), Ok(42i32));
2249
2250        let s2 = Structure::builder("test")
2251            .field("f1", "abc")
2252            .field("f2", String::from("bcd"))
2253            .field("f3", 123i32)
2254            .field_if_some("f4", Option::<i32>::None)
2255            .field_if_some("f5", Some("efg"))
2256            .field_if_some("f6", Option::<&str>::None)
2257            .field_if("f7", 42i32, true)
2258            .field_if("f8", 21i32, false)
2259            .build();
2260        assert_eq!(s, s2);
2261
2262        let mut s3 = Structure::new_empty("test");
2263
2264        s3.set_if_some("f1", Some("abc"));
2265        s3.set_if_some("f2", Some(String::from("bcd")));
2266        s3.set_if_some("f3", Some(123i32));
2267        s3.set_if_some("f4", Option::<i32>::None);
2268        s3.set_if_some("f5", Some("efg"));
2269        s3.set_if_some("f6", Option::<&str>::None);
2270        s3.set_if("f7", 42i32, true);
2271        s3.set_if("f8", 21i32, false);
2272        assert_eq!(s, s3);
2273    }
2274
2275    #[test]
2276    fn new_set_get_static() {
2277        use glib::{value, Type};
2278
2279        crate::init().unwrap();
2280
2281        let mut s = Structure::new_empty_from_static(gstr!("test"));
2282        assert_eq!(s.name(), "test");
2283
2284        static F1: &GStr = gstr!("f1");
2285        static F2: &GStr = gstr!("f2");
2286        static F3: &GStr = gstr!("f3");
2287
2288        s.set_with_static(F1, "abc");
2289        s.set_with_static_if(F2, String::from("bcd"), true);
2290        s.set_with_static_if(F3, "not_set", false);
2291
2292        assert_eq!(s.get::<&str>(F1), Ok("abc"));
2293        assert_eq!(s.get::<Option<&str>>(F2), Ok(Some("bcd")));
2294        assert_eq!(s.get_optional::<&str>(F1), Ok(Some("abc")));
2295        assert_eq!(s.get_optional::<&str>(F3), Ok(None));
2296
2297        assert_eq!(
2298            s.get::<i32>(F2),
2299            Err(GetError::from_value_get_error(
2300                idstr!("f2"),
2301                value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
2302            ))
2303        );
2304        assert_eq!(
2305            s.get::<&str>(F3),
2306            Err(GetError::new_field_not_found(idstr!("f3")))
2307        );
2308
2309        let s2 = Structure::builder("test")
2310            .field_with_static(F1, "abc")
2311            .field_with_static(F2, String::from("bcd"))
2312            .build();
2313        assert_eq!(s, s2);
2314
2315        let mut s3 = Structure::new_empty("test");
2316
2317        s3.set_with_static_if_some(F1, Some("abc"));
2318        s3.set_with_static_if_some(F2, Some(String::from("bcd")));
2319
2320        assert_eq!(s, s3);
2321    }
2322
2323    #[test]
2324    fn new_set_get_id_str() {
2325        use glib::{value, Type};
2326
2327        crate::init().unwrap();
2328
2329        let mut s = Structure::new_empty_from_id(idstr!("test"));
2330        assert_eq!(s.name(), "test");
2331        #[cfg(feature = "v1_26")]
2332        assert_eq!(s.name_id(), "test");
2333
2334        let f1 = idstr!("f1");
2335        let f2 = idstr!("f2");
2336        let f3 = idstr!("f3");
2337
2338        s.set_with_id(&f1, "abc");
2339        s.set_with_id_if(&f2, String::from("bcd"), true);
2340        s.set_with_id_if(&f3, "not_set", false);
2341
2342        assert_eq!(s.get_by_id::<&str>(&f1), Ok("abc"));
2343        assert_eq!(s.get_by_id::<&str>(f1.clone()), Ok("abc"));
2344        assert_eq!(s.get_by_id::<Option<&str>>(&f2), Ok(Some("bcd")));
2345        assert_eq!(s.get_by_id::<Option<&str>>(f2.clone()), Ok(Some("bcd")));
2346        assert_eq!(s.get_optional_by_id::<&str>(&f1), Ok(Some("abc")));
2347        assert_eq!(s.get_optional_by_id::<&str>(&f3), Ok(None));
2348
2349        assert_eq!(
2350            s.get_by_id::<i32>(&f2),
2351            Err(GetError::from_value_get_error(
2352                f2.clone(),
2353                value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
2354            ))
2355        );
2356        assert_eq!(
2357            s.get_by_id::<&str>(&f3),
2358            Err(GetError::new_field_not_found(f3.clone()))
2359        );
2360
2361        let s2 = Structure::builder("test")
2362            .field_with_id(&f1, "abc")
2363            .field_with_id(&f2, String::from("bcd"))
2364            .build();
2365        assert_eq!(s, s2);
2366
2367        let mut s3 = Structure::new_empty("test");
2368
2369        s3.set_with_id_if_some(f1, Some("abc"));
2370        s3.set_with_id_if_some(f2, Some(String::from("bcd")));
2371
2372        assert_eq!(s, s3);
2373    }
2374
2375    #[test]
2376    fn test_string_conversion() {
2377        crate::init().unwrap();
2378
2379        let a = "Test, f1=(string)abc, f2=(uint)123;";
2380
2381        let s = a.parse::<Structure>().unwrap();
2382        assert_eq!(s.get::<&str>("f1"), Ok("abc"));
2383        assert_eq!(s.get::<u32>("f2"), Ok(123));
2384
2385        assert_eq!(a, s.to_string());
2386    }
2387
2388    #[test]
2389    fn test_from_value_optional() {
2390        use glib::value::ToValue;
2391
2392        crate::init().unwrap();
2393
2394        let a = None::<&Structure>.to_value();
2395        assert!(a.get::<Option<Structure>>().unwrap().is_none());
2396        let b = "foo".parse::<Structure>().unwrap().to_value();
2397        assert!(b.get::<Option<Structure>>().unwrap().is_some());
2398    }
2399
2400    #[test]
2401    fn test_new_from_iter() {
2402        crate::init().unwrap();
2403
2404        let s = Structure::builder("test")
2405            .field("f1", "abc")
2406            .field_with_static(gstr!("f2"), String::from("bcd"))
2407            .field_with_id(idstr!("f3"), 123i32)
2408            .build();
2409
2410        let s2 = Structure::from_iter(
2411            s.name(),
2412            s.iter()
2413                .filter(|(f, _)| *f == "f1")
2414                .map(|(f, v)| (f, v.clone())),
2415        );
2416
2417        assert_eq!(s2.name(), "test");
2418        assert_eq!(s2.get::<&str>("f1"), Ok("abc"));
2419        assert!(s2.get::<&str>("f2").is_err());
2420        assert!(s2.get_by_id::<&str>(idstr!("f3")).is_err());
2421    }
2422
2423    #[test]
2424    fn test_debug() {
2425        crate::init().unwrap();
2426
2427        let s = Structure::builder("test")
2428            .field("f1", "abc")
2429            .field("f2", String::from("bcd"))
2430            .field("f3", 123i32)
2431            .field(
2432                "f4",
2433                Structure::builder("nested").field("badger", true).build(),
2434            )
2435            .field("f5", crate::Array::new(["a", "b", "c"]))
2436            .field("f6", crate::List::new(["d", "e", "f"]))
2437            .build();
2438
2439        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\"]) })");
2440    }
2441
2442    #[test]
2443    fn builder_field_from_iter() {
2444        crate::init().unwrap();
2445
2446        static SLIST: &GStr = gstr!("slist");
2447        let ilist = idstr!("ilist");
2448        let s = Structure::builder("test")
2449            .field_from_iter::<crate::Array, i32>("array", [1, 2, 3])
2450            .field_with_static_from_iter::<crate::List, i32>(SLIST, [4, 5, 6])
2451            .field_with_id_from_iter::<crate::List, i32>(&ilist, [7, 8, 9])
2452            .build();
2453        assert!(s
2454            .get::<crate::Array>("array")
2455            .unwrap()
2456            .iter()
2457            .map(|val| val.get::<i32>().unwrap())
2458            .eq([1, 2, 3]));
2459        assert!(s
2460            .get::<crate::List>("slist")
2461            .unwrap()
2462            .iter()
2463            .map(|val| val.get::<i32>().unwrap())
2464            .eq([4, 5, 6]));
2465        assert!(s
2466            .get_by_id::<crate::List>(&ilist)
2467            .unwrap()
2468            .iter()
2469            .map(|val| val.get::<i32>().unwrap())
2470            .eq([7, 8, 9]));
2471
2472        let array = Vec::<i32>::new();
2473        let s = Structure::builder("test")
2474            .field_from_iter::<crate::Array, _>("array", &array)
2475            .field_with_static_from_iter::<crate::List, _>(SLIST, &array)
2476            .field_with_id_from_iter::<crate::List, _>(&ilist, &array)
2477            .build();
2478        assert!(s.get::<crate::Array>("array").unwrap().as_ref().is_empty());
2479        assert!(s.get::<crate::List>(SLIST).unwrap().as_ref().is_empty());
2480        assert!(s
2481            .get_by_id::<crate::List>(ilist)
2482            .unwrap()
2483            .as_ref()
2484            .is_empty());
2485    }
2486
2487    #[test]
2488    fn builder_field_if_not_empty() {
2489        crate::init().unwrap();
2490
2491        static SLIST: &GStr = gstr!("slist");
2492        let ilist = idstr!("ilist");
2493        let s = Structure::builder_from_id(idstr!("test"))
2494            .field_if_not_empty::<crate::Array, i32>("array", [1, 2, 3])
2495            .field_with_static_if_not_empty::<crate::List, i32>(SLIST, [4, 5, 6])
2496            .field_with_id_if_not_empty::<crate::List, i32>(&ilist, [7, 8, 9])
2497            .build();
2498        assert!(s
2499            .get::<crate::Array>("array")
2500            .unwrap()
2501            .iter()
2502            .map(|val| val.get::<i32>().unwrap())
2503            .eq([1, 2, 3]));
2504        assert!(s
2505            .get::<crate::List>("slist")
2506            .unwrap()
2507            .iter()
2508            .map(|val| val.get::<i32>().unwrap())
2509            .eq([4, 5, 6]));
2510        assert!(s
2511            .get_by_id::<crate::List>(&ilist)
2512            .unwrap()
2513            .iter()
2514            .map(|val| val.get::<i32>().unwrap())
2515            .eq([7, 8, 9]));
2516
2517        let array = Vec::<i32>::new();
2518        let s = Structure::builder("test")
2519            .field_if_not_empty::<crate::Array, _>("array", &array)
2520            .field_with_static_if_not_empty::<crate::List, _>(SLIST, &array)
2521            .field_with_id_if_not_empty::<crate::List, _>(ilist, &array)
2522            .build();
2523        assert!(!s.has_field("array"));
2524        assert!(!s.has_field("slist"));
2525        assert!(!s.has_field("ilist"));
2526    }
2527
2528    #[test]
2529    fn nth_field_remove_field() {
2530        crate::init().unwrap();
2531
2532        let f3 = idstr!("f3");
2533        let f5 = idstr!("f5");
2534        let f8 = idstr!("f8");
2535        let mut s = Structure::builder("test")
2536            .field("f1", "abc")
2537            .field("f2", "bcd")
2538            .field_with_id(&f3, "cde")
2539            .field("f4", "def")
2540            .field_with_id(&f5, "efg")
2541            .field("f6", "fgh")
2542            .field("f7", "ghi")
2543            .field_with_id(&f8, "hij")
2544            .build();
2545
2546        assert_eq!(s.iter().next().unwrap().0, "f1");
2547        assert_eq!(
2548            s.fields().collect::<Vec<_>>(),
2549            vec!["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"]
2550        );
2551        assert!(s.has_field("f8"));
2552        assert_eq!(s.nth_field_name(7), Some(gstr!("f8")));
2553        assert!(s.nth_field_name(8).is_none());
2554
2555        #[cfg(feature = "v1_26")]
2556        assert_eq!(s.id_iter().next().unwrap().0, "f1");
2557        #[cfg(feature = "v1_26")]
2558        assert_eq!(
2559            s.field_ids().collect::<Vec<_>>(),
2560            vec!["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"]
2561        );
2562        #[cfg(feature = "v1_26")]
2563        assert!(s.has_field_by_id(&f8));
2564        #[cfg(feature = "v1_26")]
2565        assert_eq!(s.nth_field_by_id(7), Some(&f8));
2566        #[cfg(feature = "v1_26")]
2567        assert!(s.nth_field_by_id(8).is_none());
2568
2569        assert_eq!(s.nth_field_name(1), Some(gstr!("f2")));
2570        s.remove_field("f2");
2571        assert_eq!(s.nth_field_name(1), Some(gstr!("f3")));
2572        assert!(s.nth_field_name(7).is_none());
2573        assert_eq!(
2574            s.fields().collect::<Vec<_>>(),
2575            vec!["f1", "f3", "f4", "f5", "f6", "f7", "f8"]
2576        );
2577
2578        assert_eq!(s.nth_field_name(1), Some(gstr!("f3")));
2579        s.remove_field_by_id(&f3);
2580        assert_eq!(s.nth_field_name(1), Some(gstr!("f4")));
2581        assert!(s.nth_field_name(6).is_none());
2582        #[cfg(feature = "v1_26")]
2583        assert_eq!(s.nth_field_by_id(2), Some(&f5));
2584        #[cfg(feature = "v1_26")]
2585        assert!(s.nth_field_by_id(6).is_none());
2586        assert_eq!(
2587            s.fields().collect::<Vec<_>>(),
2588            vec!["f1", "f4", "f5", "f6", "f7", "f8"]
2589        );
2590
2591        s.remove_fields(["f4", "f6"]);
2592        assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f5", "f7", "f8"]);
2593
2594        s.remove_field_by_ids([&f5, &f8]);
2595        assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f7"]);
2596        #[cfg(feature = "v1_26")]
2597        assert_eq!(s.field_ids().collect::<Vec<_>>(), vec!["f1", "f7"]);
2598
2599        s.remove_all_fields();
2600        assert!(s.is_empty());
2601    }
2602
2603    #[cfg(feature = "v1_26")]
2604    #[test]
2605    fn map_in_place() {
2606        crate::init().unwrap();
2607
2608        let f1 = idstr!("f1");
2609        let f2 = idstr!("f2");
2610        let f3 = idstr!("f3");
2611        let mut s = Structure::builder_from_id(idstr!("test"))
2612            .field_with_id(&f1, "abc")
2613            .field_with_id(&f2, "bcd")
2614            .field_with_id(&f3, false)
2615            .build();
2616        assert!(!s.get_by_id::<bool>(&f3).unwrap());
2617
2618        s.map_in_place_by_id(|name, value| {
2619            if *name == f3 {
2620                *value = true.into()
2621            }
2622
2623            std::ops::ControlFlow::Continue(())
2624        });
2625        assert!(s.get_by_id::<bool>(&f3).unwrap());
2626
2627        s.map_in_place_by_id(|name, value| {
2628            match name.as_str() {
2629                "f2" => return std::ops::ControlFlow::Break(()),
2630                "f3" => *value = false.into(),
2631                _ => (),
2632            }
2633            std::ops::ControlFlow::Continue(())
2634        });
2635        assert!(s.get_by_id::<bool>(&f3).unwrap());
2636
2637        s.filter_map_in_place_by_id(|name, value| {
2638            if *name == f3 && value.get::<bool>().unwrap() {
2639                None
2640            } else {
2641                Some(value)
2642            }
2643        });
2644
2645        assert_eq!(s.field_ids().collect::<Vec<_>>(), vec![&f1, &f2]);
2646    }
2647}