gstreamer/
structure.rs

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