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 glib::{
13 prelude::*,
14 translate::*,
15 value::{FromValue, SendValue, ToSendValue},
16 IntoGStr,
17};
18
19use crate::Fraction;
20
21#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
22pub enum GetError<E: std::error::Error> {
23 #[error("GetError: Structure field with name {name} not found")]
24 FieldNotFound { name: &'static str },
25 #[error("GetError: Structure field with name {name} not retrieved")]
26 ValueGetError {
27 name: &'static str,
28 #[source]
29 error: E,
30 },
31}
32
33impl<E: std::error::Error> GetError<E> {
34 fn new_field_not_found(name: &'static str) -> Self {
35 skip_assert_initialized!();
36 GetError::FieldNotFound { name }
37 }
38
39 fn from_value_get_error(name: &'static str, error: E) -> Self {
40 skip_assert_initialized!();
41 GetError::ValueGetError { name, error }
42 }
43}
44
45#[doc(alias = "GstStructure")]
46#[repr(transparent)]
47pub struct Structure(ptr::NonNull<ffi::GstStructure>);
48unsafe impl Send for Structure {}
49unsafe impl Sync for Structure {}
50
51impl Structure {
52 #[doc(alias = "gst_structure_new")]
53 pub fn builder(name: impl IntoGStr) -> Builder {
54 skip_assert_initialized!();
55 Builder::new(name)
56 }
57
58 #[doc(alias = "gst_structure_new_empty")]
59 pub fn new_empty(name: impl IntoGStr) -> Structure {
60 assert_initialized_main_thread!();
61 unsafe {
62 let ptr = name.run_with_gstr(|name| ffi::gst_structure_new_empty(name.as_ptr()));
63 debug_assert!(!ptr.is_null());
64 Structure(ptr::NonNull::new_unchecked(ptr))
65 }
66 }
67
68 #[doc(alias = "gst_structure_new")]
69 #[deprecated = "Use `Structure::builder()` or `Structure::new_empty()`"]
70 pub fn new(name: impl IntoGStr, values: &[(&str, &(dyn ToSendValue + Sync))]) -> Structure {
71 skip_assert_initialized!();
72 let mut structure = Structure::new_empty(name);
73
74 for &(f, v) in values {
75 structure.set_value(f, v.to_send_value());
76 }
77
78 structure
79 }
80
81 #[allow(clippy::should_implement_trait)]
82 pub fn from_iter(
83 name: impl IntoGStr,
84 iter: impl IntoIterator<Item = (impl IntoGStr, SendValue)>,
85 ) -> Structure {
86 skip_assert_initialized!();
87 let mut structure = Structure::new_empty(name);
88
89 iter.into_iter()
90 .for_each(|(f, v)| structure.set_value(f, v));
91
92 structure
93 }
94}
95
96impl IntoGlibPtr<*mut ffi::GstStructure> for Structure {
97 #[inline]
98 unsafe fn into_glib_ptr(self) -> *mut ffi::GstStructure {
99 let s: ManuallyDrop = mem::ManuallyDrop::new(self);
100 s.0.as_ptr()
101 }
102}
103
104impl Deref for Structure {
105 type Target = StructureRef;
106
107 #[inline]
108 fn deref(&self) -> &StructureRef {
109 unsafe { &*(self.0.as_ptr() as *const StructureRef) }
110 }
111}
112
113impl DerefMut for Structure {
114 #[inline]
115 fn deref_mut(&mut self) -> &mut StructureRef {
116 unsafe { &mut *(self.0.as_ptr() as *mut StructureRef) }
117 }
118}
119
120impl AsRef<StructureRef> for Structure {
121 #[inline]
122 fn as_ref(&self) -> &StructureRef {
123 self.deref()
124 }
125}
126
127impl AsMut<StructureRef> for Structure {
128 #[inline]
129 fn as_mut(&mut self) -> &mut StructureRef {
130 self.deref_mut()
131 }
132}
133
134impl Clone for Structure {
135 #[inline]
136 fn clone(&self) -> Self {
137 unsafe {
138 let ptr: *mut GstStructure = ffi::gst_structure_copy(self.0.as_ref());
139 debug_assert!(!ptr.is_null());
140 Structure(ptr::NonNull::new_unchecked(ptr))
141 }
142 }
143}
144
145impl Drop for Structure {
146 #[inline]
147 fn drop(&mut self) {
148 unsafe { ffi::gst_structure_free(self.0.as_mut()) }
149 }
150}
151
152impl fmt::Debug for Structure {
153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154 f.debug_tuple(name:"Structure").field(self.as_ref()).finish()
155 }
156}
157
158impl fmt::Display for Structure {
159 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160 // Need to make sure to not call ToString::to_string() here, which
161 // we have because of the Display impl. We need StructureRef::to_string()
162 f.write_str(&StructureRef::to_string(self.as_ref()))
163 }
164}
165
166impl PartialEq for Structure {
167 fn eq(&self, other: &Structure) -> bool {
168 StructureRef::eq(self, other)
169 }
170}
171
172impl Eq for Structure {}
173
174impl PartialEq<StructureRef> for Structure {
175 fn eq(&self, other: &StructureRef) -> bool {
176 StructureRef::eq(self, other)
177 }
178}
179
180impl PartialEq<Structure> for StructureRef {
181 fn eq(&self, other: &Structure) -> bool {
182 StructureRef::eq(self:other, self)
183 }
184}
185
186impl str::FromStr for Structure {
187 type Err = glib::BoolError;
188
189 #[doc(alias = "gst_structure_from_string")]
190 fn from_str(s: &str) -> Result<Self, Self::Err> {
191 assert_initialized_main_thread!();
192 unsafe {
193 let structure: *mut GstStructure =
194 s.run_with_gstr(|s: &GStr| ffi::gst_structure_from_string(string:s.as_ptr(), end:ptr::null_mut()));
195 if structure.is_null() {
196 Err(glib::bool_error!("Failed to parse structure from string"))
197 } else {
198 Ok(Self(ptr::NonNull::new_unchecked(ptr:structure)))
199 }
200 }
201 }
202}
203
204impl Borrow<StructureRef> for Structure {
205 #[inline]
206 fn borrow(&self) -> &StructureRef {
207 self.as_ref()
208 }
209}
210
211impl BorrowMut<StructureRef> for Structure {
212 #[inline]
213 fn borrow_mut(&mut self) -> &mut StructureRef {
214 self.as_mut()
215 }
216}
217
218impl ToOwned for StructureRef {
219 type Owned = Structure;
220
221 fn to_owned(&self) -> Structure {
222 unsafe {
223 let ptr: *mut GstStructure = ffi::gst_structure_copy(&self.0);
224 debug_assert!(!ptr.is_null());
225 Structure(ptr::NonNull::new_unchecked(ptr))
226 }
227 }
228}
229
230impl glib::types::StaticType for Structure {
231 #[inline]
232 fn static_type() -> glib::types::Type {
233 unsafe { from_glib(val:ffi::gst_structure_get_type()) }
234 }
235}
236
237impl<'a> ToGlibPtr<'a, *const ffi::GstStructure> for Structure {
238 type Storage = PhantomData<&'a Self>;
239
240 #[inline]
241 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstStructure, Self> {
242 unsafe { Stash(self.0.as_ref(), PhantomData) }
243 }
244
245 #[inline]
246 fn to_glib_full(&self) -> *const ffi::GstStructure {
247 unsafe { ffi::gst_structure_copy(self.0.as_ref()) }
248 }
249}
250
251impl<'a> ToGlibPtr<'a, *mut ffi::GstStructure> for Structure {
252 type Storage = PhantomData<&'a Self>;
253
254 #[inline]
255 fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GstStructure, Self> {
256 unsafe {
257 Stash(
258 self.0.as_ref() as *const ffi::GstStructure as *mut ffi::GstStructure,
259 PhantomData,
260 )
261 }
262 }
263
264 #[inline]
265 fn to_glib_full(&self) -> *mut ffi::GstStructure {
266 unsafe { ffi::gst_structure_copy(self.0.as_ref()) }
267 }
268}
269
270impl<'a> ToGlibPtrMut<'a, *mut ffi::GstStructure> for Structure {
271 type Storage = PhantomData<&'a mut Self>;
272
273 #[inline]
274 fn to_glib_none_mut(&'a mut self) -> StashMut<*mut ffi::GstStructure, Self> {
275 unsafe { StashMut(self.0.as_mut(), PhantomData) }
276 }
277}
278
279impl FromGlibPtrNone<*const ffi::GstStructure> for Structure {
280 #[inline]
281 unsafe fn from_glib_none(ptr: *const ffi::GstStructure) -> Self {
282 debug_assert!(!ptr.is_null());
283 let ptr: *mut GstStructure = ffi::gst_structure_copy(structure:ptr);
284 debug_assert!(!ptr.is_null());
285 Structure(ptr::NonNull::new_unchecked(ptr))
286 }
287}
288
289impl FromGlibPtrNone<*mut ffi::GstStructure> for Structure {
290 #[inline]
291 unsafe fn from_glib_none(ptr: *mut ffi::GstStructure) -> Self {
292 debug_assert!(!ptr.is_null());
293 let ptr: *mut GstStructure = ffi::gst_structure_copy(structure:ptr);
294 debug_assert!(!ptr.is_null());
295 Structure(ptr::NonNull::new_unchecked(ptr))
296 }
297}
298
299impl FromGlibPtrFull<*const ffi::GstStructure> for Structure {
300 #[inline]
301 unsafe fn from_glib_full(ptr: *const ffi::GstStructure) -> Self {
302 debug_assert!(!ptr.is_null());
303 Structure(ptr::NonNull::new_unchecked(ptr as *mut ffi::GstStructure))
304 }
305}
306
307impl FromGlibPtrFull<*mut ffi::GstStructure> for Structure {
308 #[inline]
309 unsafe fn from_glib_full(ptr: *mut ffi::GstStructure) -> Self {
310 debug_assert!(!ptr.is_null());
311 Structure(ptr::NonNull::new_unchecked(ptr))
312 }
313}
314
315impl FromGlibPtrBorrow<*const ffi::GstStructure> for Structure {
316 #[inline]
317 unsafe fn from_glib_borrow(ptr: *const ffi::GstStructure) -> Borrowed<Self> {
318 Borrowed::new(val:from_glib_full(ptr))
319 }
320}
321
322impl FromGlibPtrBorrow<*mut ffi::GstStructure> for Structure {
323 #[inline]
324 unsafe fn from_glib_borrow(ptr: *mut ffi::GstStructure) -> Borrowed<Self> {
325 Borrowed::new(val:from_glib_full(ptr))
326 }
327}
328
329impl glib::value::ValueType for Structure {
330 type Type = Self;
331}
332
333impl glib::value::ValueTypeOptional for Structure {}
334
335unsafe impl<'a> glib::value::FromValue<'a> for Structure {
336 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
337
338 unsafe fn from_value(value: &'a glib::Value) -> Self {
339 skip_assert_initialized!();
340 from_glib_none(
341 ptr:glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstStructure
342 )
343 }
344}
345
346impl glib::value::ToValue for Structure {
347 fn to_value(&self) -> glib::Value {
348 let mut value: Value = glib::Value::for_value_type::<Self>();
349 unsafe {
350 glib::gobject_ffi::g_value_set_boxed(
351 value:value.to_glib_none_mut().0,
352 v_boxed:glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(self).0
353 as *mut _,
354 )
355 }
356 value
357 }
358
359 fn value_type(&self) -> glib::Type {
360 Self::static_type()
361 }
362}
363
364impl glib::value::ToValueOptional for Structure {
365 fn to_value_optional(s: Option<&Self>) -> glib::Value {
366 skip_assert_initialized!();
367 let mut value: Value = glib::Value::for_value_type::<Self>();
368 unsafe {
369 glib::gobject_ffi::g_value_set_boxed(
370 value:value.to_glib_none_mut().0,
371 v_boxed:glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(&s).0
372 as *mut _,
373 )
374 }
375 value
376 }
377}
378
379impl From<Structure> for glib::Value {
380 fn from(v: Structure) -> glib::Value {
381 skip_assert_initialized!();
382 let mut value: Value = glib::Value::for_value_type::<Structure>();
383 unsafe {
384 glib::gobject_ffi::g_value_take_boxed(
385 value:value.to_glib_none_mut().0,
386 v_boxed:glib::translate::IntoGlibPtr::<*mut ffi::GstStructure>::into_glib_ptr(self:v) as *mut _,
387 )
388 }
389 value
390 }
391}
392
393impl GlibPtrDefault for Structure {
394 type GlibType = *mut ffi::GstStructure;
395}
396
397unsafe impl TransparentPtrType for Structure {}
398
399#[repr(transparent)]
400#[doc(alias = "GstStructure")]
401pub struct StructureRef(ffi::GstStructure);
402
403unsafe impl Send for StructureRef {}
404unsafe impl Sync for StructureRef {}
405
406impl StructureRef {
407 #[inline]
408 pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstStructure) -> &'a StructureRef {
409 debug_assert!(!ptr.is_null());
410
411 &*(ptr as *mut StructureRef)
412 }
413
414 #[inline]
415 pub unsafe fn from_glib_borrow_mut<'a>(ptr: *mut ffi::GstStructure) -> &'a mut StructureRef {
416 debug_assert!(!ptr.is_null());
417
418 &mut *(ptr as *mut StructureRef)
419 }
420
421 #[inline]
422 pub fn as_ptr(&self) -> *const ffi::GstStructure {
423 self as *const Self as *const ffi::GstStructure
424 }
425
426 #[inline]
427 pub fn as_mut_ptr(&self) -> *mut ffi::GstStructure {
428 self as *const Self as *mut ffi::GstStructure
429 }
430
431 #[doc(alias = "gst_structure_get")]
432 pub fn get<'a, T: FromValue<'a>>(
433 &'a self,
434 name: impl IntoGStr,
435 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
436 {
437 let name = glib::Quark::from_str(name);
438 self.get_by_quark(name)
439 }
440
441 #[doc(alias = "gst_structure_get")]
442 pub fn get_optional<'a, T: FromValue<'a>>(
443 &'a self,
444 name: impl IntoGStr,
445 ) -> Result<
446 Option<T>,
447 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
448 > {
449 let name = glib::Quark::from_str(name);
450 self.get_optional_by_quark(name)
451 }
452
453 #[doc(alias = "get_value")]
454 #[doc(alias = "gst_structure_get_value")]
455 pub fn value(
456 &self,
457 name: impl IntoGStr,
458 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
459 let name = glib::Quark::from_str(name);
460 self.value_by_quark(name)
461 }
462
463 #[doc(alias = "gst_structure_id_get")]
464 pub fn get_by_quark<'a, T: FromValue<'a>>(
465 &'a self,
466 name: glib::Quark,
467 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
468 {
469 self.value_by_quark(name)
470 .map_err(|err| match err {
471 GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
472 _ => unreachable!(),
473 })?
474 .get()
475 .map_err(|err| GetError::from_value_get_error(name.as_str(), err))
476 }
477
478 #[doc(alias = "gst_structure_id_get")]
479 pub fn get_optional_by_quark<'a, T: FromValue<'a>>(
480 &'a self,
481 name: glib::Quark,
482 ) -> Result<
483 Option<T>,
484 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
485 > {
486 self.value_by_quark(name)
487 .ok()
488 .map(|v| v.get())
489 .transpose()
490 .map_err(|err| GetError::from_value_get_error(name.as_str(), err))
491 }
492
493 #[doc(alias = "gst_structure_id_get_value")]
494 pub fn value_by_quark(
495 &self,
496 name: glib::Quark,
497 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
498 unsafe {
499 let value = ffi::gst_structure_id_get_value(&self.0, name.into_glib());
500
501 if value.is_null() {
502 return Err(GetError::new_field_not_found(name.as_str()));
503 }
504
505 Ok(&*(value as *const SendValue))
506 }
507 }
508
509 #[doc(alias = "gst_structure_set")]
510 pub fn set(&mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) {
511 let value = glib::SendValue::from_owned(value);
512 self.set_value(name, value);
513 }
514
515 #[doc(alias = "gst_structure_set_value")]
516 pub fn set_value(&mut self, name: impl IntoGStr, value: SendValue) {
517 unsafe {
518 name.run_with_gstr(|name| {
519 ffi::gst_structure_take_value(&mut self.0, name.as_ptr(), &mut value.into_raw())
520 });
521 }
522 }
523
524 #[doc(alias = "gst_structure_id_set")]
525 pub fn set_by_quark(&mut self, name: glib::Quark, value: impl Into<glib::Value> + Send) {
526 let value = glib::SendValue::from_owned(value);
527 self.set_value_by_quark(name, value);
528 }
529
530 #[doc(alias = "gst_structure_id_set_value")]
531 pub fn set_value_by_quark(&mut self, name: glib::Quark, value: SendValue) {
532 unsafe {
533 ffi::gst_structure_id_take_value(&mut self.0, name.into_glib(), &mut value.into_raw());
534 }
535 }
536
537 #[doc(alias = "get_name")]
538 #[doc(alias = "gst_structure_get_name")]
539 pub fn name<'a>(&self) -> &'a glib::GStr {
540 unsafe { glib::GStr::from_ptr(ffi::gst_structure_get_name(&self.0)) }
541 }
542
543 #[doc(alias = "gst_structure_get_name_id")]
544 pub fn name_quark(&self) -> glib::Quark {
545 unsafe { from_glib(ffi::gst_structure_get_name_id(&self.0)) }
546 }
547
548 #[doc(alias = "gst_structure_set_name")]
549 pub fn set_name(&mut self, name: impl IntoGStr) {
550 unsafe {
551 name.run_with_gstr(|name| ffi::gst_structure_set_name(&mut self.0, name.as_ptr()))
552 }
553 }
554
555 #[doc(alias = "gst_structure_has_name")]
556 pub fn has_name(&self, name: &str) -> bool {
557 self.name() == name
558 }
559
560 #[doc(alias = "gst_structure_has_field")]
561 pub fn has_field(&self, field: impl IntoGStr) -> bool {
562 unsafe {
563 field.run_with_gstr(|field| {
564 from_glib(ffi::gst_structure_has_field(&self.0, field.as_ptr()))
565 })
566 }
567 }
568
569 #[doc(alias = "gst_structure_has_field_typed")]
570 pub fn has_field_with_type(&self, field: impl IntoGStr, type_: glib::Type) -> bool {
571 unsafe {
572 field.run_with_gstr(|field| {
573 from_glib(ffi::gst_structure_has_field_typed(
574 &self.0,
575 field.as_ptr(),
576 type_.into_glib(),
577 ))
578 })
579 }
580 }
581
582 #[doc(alias = "gst_structure_id_has_field")]
583 pub fn has_field_by_quark(&self, field: glib::Quark) -> bool {
584 unsafe { from_glib(ffi::gst_structure_id_has_field(&self.0, field.into_glib())) }
585 }
586
587 #[doc(alias = "gst_structure_id_has_field_typed")]
588 pub fn has_field_with_type_by_quark(&self, field: glib::Quark, type_: glib::Type) -> bool {
589 unsafe {
590 from_glib(ffi::gst_structure_id_has_field_typed(
591 &self.0,
592 field.into_glib(),
593 type_.into_glib(),
594 ))
595 }
596 }
597
598 #[doc(alias = "gst_structure_remove_field")]
599 pub fn remove_field(&mut self, field: impl IntoGStr) {
600 unsafe {
601 field.run_with_gstr(|field| {
602 ffi::gst_structure_remove_field(&mut self.0, field.as_ptr())
603 });
604 }
605 }
606
607 #[doc(alias = "gst_structure_remove_fields")]
608 pub fn remove_fields(&mut self, fields: impl IntoIterator<Item = impl IntoGStr>) {
609 for f in fields.into_iter() {
610 self.remove_field(f)
611 }
612 }
613
614 #[doc(alias = "gst_structure_remove_all_fields")]
615 pub fn remove_all_fields(&mut self) {
616 unsafe {
617 ffi::gst_structure_remove_all_fields(&mut self.0);
618 }
619 }
620
621 pub fn fields(&self) -> FieldIterator {
622 FieldIterator::new(self)
623 }
624
625 pub fn iter(&self) -> Iter {
626 Iter::new(self)
627 }
628
629 #[doc(alias = "get_nth_field_name")]
630 #[doc(alias = "gst_structure_nth_field_name")]
631 pub fn nth_field_name<'a>(&self, idx: u32) -> Option<&'a glib::GStr> {
632 if idx >= self.n_fields() {
633 return None;
634 }
635
636 unsafe {
637 let field_name = ffi::gst_structure_nth_field_name(&self.0, idx);
638 debug_assert!(!field_name.is_null());
639
640 Some(glib::GStr::from_ptr(field_name))
641 }
642 }
643
644 #[doc(alias = "gst_structure_n_fields")]
645 pub fn n_fields(&self) -> u32 {
646 unsafe { ffi::gst_structure_n_fields(&self.0) as u32 }
647 }
648
649 #[doc(alias = "gst_structure_can_intersect")]
650 pub fn can_intersect(&self, other: &StructureRef) -> bool {
651 unsafe { from_glib(ffi::gst_structure_can_intersect(&self.0, &other.0)) }
652 }
653
654 #[doc(alias = "gst_structure_intersect")]
655 pub fn intersect(&self, other: &StructureRef) -> Option<Structure> {
656 unsafe { from_glib_full(ffi::gst_structure_intersect(&self.0, &other.0)) }
657 }
658
659 #[doc(alias = "gst_structure_is_subset")]
660 pub fn is_subset(&self, superset: &StructureRef) -> bool {
661 unsafe { from_glib(ffi::gst_structure_is_subset(&self.0, &superset.0)) }
662 }
663
664 #[doc(alias = "gst_structure_fixate")]
665 pub fn fixate(&mut self) {
666 unsafe { ffi::gst_structure_fixate(&mut self.0) }
667 }
668
669 #[doc(alias = "gst_structure_fixate_field")]
670 pub fn fixate_field(&mut self, name: impl IntoGStr) -> bool {
671 unsafe {
672 name.run_with_gstr(|name| {
673 from_glib(ffi::gst_structure_fixate_field(&mut self.0, name.as_ptr()))
674 })
675 }
676 }
677
678 #[doc(alias = "gst_structure_fixate_field_boolean")]
679 pub fn fixate_field_bool(&mut self, name: impl IntoGStr, target: bool) -> bool {
680 unsafe {
681 name.run_with_gstr(|name| {
682 from_glib(ffi::gst_structure_fixate_field_boolean(
683 &mut self.0,
684 name.as_ptr(),
685 target.into_glib(),
686 ))
687 })
688 }
689 }
690
691 #[doc(alias = "gst_structure_fixate_field_string")]
692 pub fn fixate_field_str(&mut self, name: impl IntoGStr, target: impl IntoGStr) -> bool {
693 unsafe {
694 name.run_with_gstr(|name| {
695 target.run_with_gstr(|target| {
696 from_glib(ffi::gst_structure_fixate_field_string(
697 &mut self.0,
698 name.as_ptr(),
699 target.as_ptr(),
700 ))
701 })
702 })
703 }
704 }
705
706 #[doc(alias = "gst_structure_fixate_field_nearest_double")]
707 pub fn fixate_field_nearest_double(&mut self, name: impl IntoGStr, target: f64) -> bool {
708 unsafe {
709 name.run_with_gstr(|name| {
710 from_glib(ffi::gst_structure_fixate_field_nearest_double(
711 &mut self.0,
712 name.as_ptr(),
713 target,
714 ))
715 })
716 }
717 }
718
719 #[doc(alias = "gst_structure_fixate_field_nearest_fraction")]
720 pub fn fixate_field_nearest_fraction(
721 &mut self,
722 name: impl IntoGStr,
723 target: impl Into<Fraction>,
724 ) -> bool {
725 skip_assert_initialized!();
726
727 let target = target.into();
728 unsafe {
729 name.run_with_gstr(|name| {
730 from_glib(ffi::gst_structure_fixate_field_nearest_fraction(
731 &mut self.0,
732 name.as_ptr(),
733 target.numer(),
734 target.denom(),
735 ))
736 })
737 }
738 }
739
740 #[doc(alias = "gst_structure_fixate_field_nearest_int")]
741 pub fn fixate_field_nearest_int(&mut self, name: impl IntoGStr, target: i32) -> bool {
742 unsafe {
743 name.run_with_gstr(|name| {
744 from_glib(ffi::gst_structure_fixate_field_nearest_int(
745 &mut self.0,
746 name.as_ptr(),
747 target,
748 ))
749 })
750 }
751 }
752
753 #[cfg(feature = "v1_20")]
754 #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
755 #[doc(alias = "gst_structure_serialize")]
756 pub fn serialize(&self, flags: crate::SerializeFlags) -> glib::GString {
757 unsafe { from_glib_full(ffi::gst_structure_serialize(&self.0, flags.into_glib())) }
758 }
759
760 #[doc(alias = "gst_structure_foreach")]
761 pub fn foreach<F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>>(
762 &self,
763 mut func: F,
764 ) -> bool {
765 unsafe {
766 unsafe extern "C" fn trampoline<
767 F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>,
768 >(
769 quark: glib::ffi::GQuark,
770 value: *const glib::gobject_ffi::GValue,
771 user_data: glib::ffi::gpointer,
772 ) -> glib::ffi::gboolean {
773 let func = &mut *(user_data as *mut F);
774 let res = func(from_glib(quark), &*(value as *const glib::Value));
775
776 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
777 }
778 let func = &mut func as *mut F;
779 from_glib(ffi::gst_structure_foreach(
780 self.as_ptr(),
781 Some(trampoline::<F>),
782 func as glib::ffi::gpointer,
783 ))
784 }
785 }
786
787 #[doc(alias = "gst_structure_map_in_place")]
788 pub fn map_in_place<F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>>(
789 &mut self,
790 mut func: F,
791 ) -> bool {
792 unsafe {
793 unsafe extern "C" fn trampoline<
794 F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>,
795 >(
796 quark: glib::ffi::GQuark,
797 value: *mut glib::gobject_ffi::GValue,
798 user_data: glib::ffi::gpointer,
799 ) -> glib::ffi::gboolean {
800 let func = &mut *(user_data as *mut F);
801 let res = func(from_glib(quark), &mut *(value as *mut glib::Value));
802
803 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
804 }
805 let func = &mut func as *mut F;
806 from_glib(ffi::gst_structure_map_in_place(
807 self.as_mut_ptr(),
808 Some(trampoline::<F>),
809 func as glib::ffi::gpointer,
810 ))
811 }
812 }
813
814 #[doc(alias = "gst_structure_filter_and_map_in_place")]
815 pub fn filter_map_in_place<F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>>(
816 &mut self,
817 mut func: F,
818 ) {
819 unsafe {
820 unsafe extern "C" fn trampoline<
821 F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>,
822 >(
823 quark: glib::ffi::GQuark,
824 value: *mut glib::gobject_ffi::GValue,
825 user_data: glib::ffi::gpointer,
826 ) -> glib::ffi::gboolean {
827 let func = &mut *(user_data as *mut F);
828
829 let v = mem::replace(
830 &mut *(value as *mut glib::Value),
831 glib::Value::uninitialized(),
832 );
833 match func(from_glib(quark), v) {
834 None => glib::ffi::GFALSE,
835 Some(v) => {
836 *value = v.into_raw();
837 glib::ffi::GTRUE
838 }
839 }
840 }
841
842 let func = &mut func as *mut F;
843 ffi::gst_structure_filter_and_map_in_place(
844 self.as_mut_ptr(),
845 Some(trampoline::<F>),
846 func as glib::ffi::gpointer,
847 );
848 }
849 }
850}
851
852impl fmt::Display for StructureRef {
853 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
854 let s: GString = unsafe { glib::GString::from_glib_full(ptr:ffi::gst_structure_to_string(&self.0)) };
855 f.write_str(&s)
856 }
857}
858
859impl fmt::Debug for StructureRef {
860 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
861 let mut debug: DebugStruct<'_, '_> = f.debug_struct(self.name());
862
863 for (id: &GStr, field: &SendValue) in self.iter() {
864 if field.type_() == Structure::static_type() {
865 let s: Structure = field.get::<Structure>().unwrap();
866 debug.field(name:id, &s);
867 } else if field.type_() == crate::Array::static_type() {
868 let arr: Array = field.get::<crate::Array>().unwrap();
869 debug.field(name:id, &arr);
870 } else if field.type_() == crate::List::static_type() {
871 let list: List = field.get::<crate::List>().unwrap();
872 debug.field(name:id, &list);
873 } else {
874 debug.field(name:id, &field);
875 }
876 }
877
878 debug.finish()
879 }
880}
881
882impl PartialEq for StructureRef {
883 #[doc(alias = "gst_structure_is_equal")]
884 fn eq(&self, other: &StructureRef) -> bool {
885 unsafe { from_glib(val:ffi::gst_structure_is_equal(&self.0, &other.0)) }
886 }
887}
888
889impl Eq for StructureRef {}
890
891impl glib::types::StaticType for StructureRef {
892 #[inline]
893 fn static_type() -> glib::types::Type {
894 unsafe { from_glib(val:ffi::gst_structure_get_type()) }
895 }
896}
897
898unsafe impl<'a> glib::value::FromValue<'a> for &'a StructureRef {
899 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
900
901 unsafe fn from_value(value: &'a glib::Value) -> Self {
902 skip_assert_initialized!();
903 &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const StructureRef)
904 }
905}
906
907impl glib::value::ToValue for StructureRef {
908 fn to_value(&self) -> glib::Value {
909 let mut value: Value = glib::Value::for_value_type::<Structure>();
910 unsafe {
911 glib::gobject_ffi::g_value_set_boxed(
912 value:value.to_glib_none_mut().0,
913 self.as_ptr() as *mut _,
914 )
915 }
916 value
917 }
918
919 fn value_type(&self) -> glib::Type {
920 Self::static_type()
921 }
922}
923
924impl glib::value::ToValueOptional for StructureRef {
925 fn to_value_optional(s: Option<&Self>) -> glib::Value {
926 skip_assert_initialized!();
927 let mut value: Value = glib::Value::for_value_type::<Structure>();
928 unsafe {
929 glib::gobject_ffi::g_value_set_boxed(
930 value:value.to_glib_none_mut().0,
931 v_boxed:s.map(|s| s.as_ptr()).unwrap_or(default:ptr::null()) as *mut _,
932 )
933 }
934 value
935 }
936}
937
938#[derive(Debug)]
939pub struct FieldIterator<'a> {
940 structure: &'a StructureRef,
941 idx: usize,
942 n_fields: usize,
943}
944
945impl<'a> FieldIterator<'a> {
946 fn new(structure: &'a StructureRef) -> FieldIterator<'a> {
947 skip_assert_initialized!();
948 let n_fields: u32 = structure.n_fields();
949
950 FieldIterator {
951 structure,
952 idx: 0,
953 n_fields: n_fields as usize,
954 }
955 }
956}
957
958impl<'a> Iterator for FieldIterator<'a> {
959 type Item = &'static glib::GStr;
960
961 fn next(&mut self) -> Option<Self::Item> {
962 if self.idx >= self.n_fields {
963 return None;
964 }
965
966 let field_name: &GStr = self.structure.nth_field_name(self.idx as u32).unwrap();
967 self.idx += 1;
968
969 Some(field_name)
970 }
971
972 fn size_hint(&self) -> (usize, Option<usize>) {
973 let remaining: usize = self.n_fields - self.idx;
974
975 (remaining, Some(remaining))
976 }
977}
978
979impl<'a> DoubleEndedIterator for FieldIterator<'a> {
980 fn next_back(&mut self) -> Option<Self::Item> {
981 if self.idx == self.n_fields {
982 return None;
983 }
984
985 self.n_fields -= 1;
986 Some(self.structure.nth_field_name(self.n_fields as u32).unwrap())
987 }
988}
989
990impl<'a> ExactSizeIterator for FieldIterator<'a> {}
991
992impl<'a> std::iter::FusedIterator for FieldIterator<'a> {}
993
994#[derive(Debug)]
995pub struct Iter<'a> {
996 iter: FieldIterator<'a>,
997}
998
999impl<'a> Iter<'a> {
1000 fn new(structure: &'a StructureRef) -> Iter<'a> {
1001 skip_assert_initialized!();
1002 Iter {
1003 iter: FieldIterator::new(structure),
1004 }
1005 }
1006}
1007
1008impl<'a> Iterator for Iter<'a> {
1009 type Item = (&'static glib::GStr, &'a SendValue);
1010
1011 fn next(&mut self) -> Option<Self::Item> {
1012 let f = self.iter.next()?;
1013 let v = self.iter.structure.value(f);
1014 Some((f, v.unwrap()))
1015 }
1016
1017 fn size_hint(&self) -> (usize, Option<usize>) {
1018 self.iter.size_hint()
1019 }
1020
1021 fn count(self) -> usize {
1022 self.iter.count()
1023 }
1024
1025 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1026 let f = self.iter.nth(n)?;
1027 let v = self.iter.structure.value(f);
1028 Some((f, v.unwrap()))
1029 }
1030
1031 fn last(self) -> Option<Self::Item> {
1032 let structure = self.iter.structure;
1033 let f = self.iter.last()?;
1034 let v = structure.value(f);
1035 Some((f, v.unwrap()))
1036 }
1037}
1038
1039impl<'a> DoubleEndedIterator for Iter<'a> {
1040 fn next_back(&mut self) -> Option<Self::Item> {
1041 let f: &GStr = self.iter.next_back()?;
1042 let v: Result<&SendValue, GetError<…>> = self.iter.structure.value(name:f);
1043 Some((f, v.unwrap()))
1044 }
1045
1046 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1047 let f: &GStr = self.iter.nth_back(n)?;
1048 let v: Result<&SendValue, GetError<…>> = self.iter.structure.value(name:f);
1049 Some((f, v.unwrap()))
1050 }
1051}
1052
1053impl<'a> ExactSizeIterator for Iter<'a> {}
1054
1055impl<'a> std::iter::FusedIterator for Iter<'a> {}
1056
1057impl<'a> IntoIterator for &'a StructureRef {
1058 type IntoIter = Iter<'a>;
1059 type Item = (&'static glib::GStr, &'a SendValue);
1060
1061 fn into_iter(self) -> Self::IntoIter {
1062 self.iter()
1063 }
1064}
1065
1066impl<'a> std::iter::Extend<(&'a str, SendValue)> for StructureRef {
1067 fn extend<T: IntoIterator<Item = (&'a str, SendValue)>>(&mut self, iter: T) {
1068 iter.into_iter().for_each(|(f: &str, v: SendValue)| self.set_value(name:f, value:v));
1069 }
1070}
1071
1072impl<'a> std::iter::Extend<(&'a glib::GStr, SendValue)> for StructureRef {
1073 fn extend<T: IntoIterator<Item = (&'a glib::GStr, SendValue)>>(&mut self, iter: T) {
1074 iter.into_iter().for_each(|(f: &GStr, v: SendValue)| self.set_value(name:f, value:v));
1075 }
1076}
1077
1078impl std::iter::Extend<(String, SendValue)> for StructureRef {
1079 fn extend<T: IntoIterator<Item = (String, SendValue)>>(&mut self, iter: T) {
1080 iter.into_iter().for_each(|(f: String, v: SendValue)| self.set_value(&f, value:v));
1081 }
1082}
1083
1084impl std::iter::Extend<(glib::GString, SendValue)> for StructureRef {
1085 fn extend<T: IntoIterator<Item = (glib::GString, SendValue)>>(&mut self, iter: T) {
1086 iter.into_iter().for_each(|(f: GString, v: SendValue)| self.set_value(&f, value:v));
1087 }
1088}
1089
1090impl std::iter::Extend<(glib::Quark, SendValue)> for StructureRef {
1091 fn extend<T: IntoIterator<Item = (glib::Quark, SendValue)>>(&mut self, iter: T) {
1092 iter::IntoIter.into_iter()
1093 .for_each(|(f: Quark, v: SendValue)| self.set_value_by_quark(name:f, value:v));
1094 }
1095}
1096
1097#[derive(Debug)]
1098#[must_use = "The builder must be built to be used"]
1099pub struct Builder {
1100 s: Structure,
1101}
1102
1103impl Builder {
1104 fn new(name: impl IntoGStr) -> Self {
1105 skip_assert_initialized!();
1106 Builder {
1107 s: Structure::new_empty(name),
1108 }
1109 }
1110
1111 pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self {
1112 self.s.set(name, value);
1113 self
1114 }
1115
1116 #[must_use = "Building the structure without using it has no effect"]
1117 pub fn build(self) -> Structure {
1118 self.s
1119 }
1120}
1121
1122#[cfg(test)]
1123mod tests {
1124 use super::*;
1125
1126 #[test]
1127 #[allow(deprecated)]
1128 fn new_set_get() {
1129 use glib::{value, Type};
1130
1131 crate::init().unwrap();
1132
1133 let mut s = Structure::new_empty("test");
1134 assert_eq!(s.name(), "test");
1135
1136 s.set("f1", "abc");
1137 s.set("f2", &String::from("bcd"));
1138 s.set("f3", 123i32);
1139
1140 assert_eq!(s.get::<&str>("f1"), Ok("abc"));
1141 assert_eq!(s.get::<Option<&str>>("f2"), Ok(Some("bcd")));
1142 assert_eq!(s.get::<i32>("f3"), Ok(123i32));
1143 assert_eq!(s.get_optional::<&str>("f1"), Ok(Some("abc")));
1144 assert_eq!(s.get_optional::<&str>("f4"), Ok(None));
1145 assert_eq!(s.get_optional::<i32>("f3"), Ok(Some(123i32)));
1146 assert_eq!(s.get_optional::<i32>("f4"), Ok(None));
1147
1148 assert_eq!(
1149 s.get::<i32>("f2"),
1150 Err(GetError::from_value_get_error(
1151 "f2",
1152 value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
1153 ))
1154 );
1155 assert_eq!(
1156 s.get::<bool>("f3"),
1157 Err(GetError::from_value_get_error(
1158 "f3",
1159 value::ValueTypeMismatchError::new(Type::I32, Type::BOOL),
1160 ))
1161 );
1162 assert_eq!(
1163 s.get::<&str>("f4"),
1164 Err(GetError::new_field_not_found("f4"))
1165 );
1166 assert_eq!(s.get::<i32>("f4"), Err(GetError::new_field_not_found("f4")));
1167
1168 assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f2", "f3"]);
1169
1170 let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>();
1171 assert_eq!(v.len(), 3);
1172 assert_eq!(v[0].0, "f1");
1173 assert_eq!(v[0].1.get::<&str>(), Ok("abc"));
1174 assert_eq!(v[1].0, "f2");
1175 assert_eq!(v[1].1.get::<&str>(), Ok("bcd"));
1176 assert_eq!(v[2].0, "f3");
1177 assert_eq!(v[2].1.get::<i32>(), Ok(123i32));
1178
1179 let s2 = Structure::new("test", &[("f1", &"abc"), ("f2", &"bcd"), ("f3", &123i32)]);
1180 assert_eq!(s, s2);
1181 }
1182
1183 #[test]
1184 fn test_builder() {
1185 crate::init().unwrap();
1186
1187 let s = Structure::builder("test")
1188 .field("f1", "abc")
1189 .field("f2", String::from("bcd"))
1190 .field("f3", 123i32)
1191 .build();
1192
1193 assert_eq!(s.name(), "test");
1194 assert_eq!(s.get::<&str>("f1"), Ok("abc"));
1195 assert_eq!(s.get::<&str>("f2"), Ok("bcd"));
1196 assert_eq!(s.get::<i32>("f3"), Ok(123i32));
1197 }
1198
1199 #[test]
1200 fn test_string_conversion() {
1201 crate::init().unwrap();
1202
1203 let a = "Test, f1=(string)abc, f2=(uint)123;";
1204
1205 let s = a.parse::<Structure>().unwrap();
1206 assert_eq!(s.get::<&str>("f1"), Ok("abc"));
1207 assert_eq!(s.get::<u32>("f2"), Ok(123));
1208
1209 assert_eq!(a, s.to_string());
1210 }
1211
1212 #[test]
1213 fn test_from_value_optional() {
1214 use glib::ToValue;
1215
1216 crate::init().unwrap();
1217
1218 let a = None::<&Structure>.to_value();
1219 assert!(a.get::<Option<Structure>>().unwrap().is_none());
1220 let b = "foo".parse::<Structure>().unwrap().to_value();
1221 assert!(b.get::<Option<Structure>>().unwrap().is_some());
1222 }
1223
1224 #[test]
1225 fn test_new_from_iter() {
1226 crate::init().unwrap();
1227
1228 let s = Structure::builder("test")
1229 .field("f1", "abc")
1230 .field("f2", String::from("bcd"))
1231 .field("f3", 123i32)
1232 .build();
1233
1234 let s2 = Structure::from_iter(
1235 s.name(),
1236 s.iter()
1237 .filter(|(f, _)| *f == "f1")
1238 .map(|(f, v)| (f, v.clone())),
1239 );
1240
1241 assert_eq!(s2.name(), "test");
1242 assert_eq!(s2.get::<&str>("f1"), Ok("abc"));
1243 assert!(s2.get::<&str>("f2").is_err());
1244 assert!(s2.get::<&str>("f3").is_err());
1245 }
1246
1247 #[test]
1248 fn test_debug() {
1249 crate::init().unwrap();
1250
1251 let s = Structure::builder("test")
1252 .field("f1", "abc")
1253 .field("f2", String::from("bcd"))
1254 .field("f3", 123i32)
1255 .field(
1256 "f4",
1257 Structure::builder("nested").field("badger", true).build(),
1258 )
1259 .field("f5", crate::Array::new(["a", "b", "c"]))
1260 .field("f6", crate::List::new(["d", "e", "f"]))
1261 .build();
1262
1263 assert_eq!(format!("{s:?}"), "Structure(test { f1: (gchararray) \"abc\", f2: (gchararray) \"bcd\", f3: (gint) 123, f4: Structure(nested { badger: (gboolean) TRUE }), f5: Array([(gchararray) \"a\", (gchararray) \"b\", (gchararray) \"c\"]), f6: List([(gchararray) \"d\", (gchararray) \"e\", (gchararray) \"f\"]) })");
1264 }
1265}
1266