1use 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, Value},
16 IntoGStr,
17};
18
19use crate::{ffi, 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")]
150#[repr(transparent)]
151pub struct Structure(ptr::NonNull<ffi::GstStructure>);
152unsafe impl Send for Structure {}
153unsafe impl Sync for Structure {}
154
155impl Structure {
156 #[doc(alias = "gst_structure_new")]
157 pub fn builder(name: impl IntoGStr) -> Builder {
158 skip_assert_initialized!();
159 Builder::new(name)
160 }
161
162 #[doc(alias = "gst_structure_new_empty")]
174 pub fn new_empty(name: impl IntoGStr) -> Structure {
175 assert_initialized_main_thread!();
176 unsafe {
177 let ptr = name.run_with_gstr(|name| ffi::gst_structure_new_empty(name.as_ptr()));
178 debug_assert!(!ptr.is_null());
179 Structure(ptr::NonNull::new_unchecked(ptr))
180 }
181 }
182
183 #[allow(clippy::should_implement_trait)]
184 pub fn from_iter(
185 name: impl IntoGStr,
186 iter: impl IntoIterator<Item = (impl IntoGStr, SendValue)>,
187 ) -> Structure {
188 skip_assert_initialized!();
189 let mut structure = Structure::new_empty(name);
190
191 iter.into_iter()
192 .for_each(|(f, v)| structure.set_value(f, v));
193
194 structure
195 }
196}
197
198impl IntoGlibPtr<*mut ffi::GstStructure> for Structure {
199 #[inline]
200 unsafe fn into_glib_ptr(self) -> *mut ffi::GstStructure {
201 let s = mem::ManuallyDrop::new(self);
202 s.0.as_ptr()
203 }
204}
205
206impl Deref for Structure {
207 type Target = StructureRef;
208
209 #[inline]
210 fn deref(&self) -> &StructureRef {
211 unsafe { &*(self.0.as_ptr() as *const StructureRef) }
212 }
213}
214
215impl DerefMut for Structure {
216 #[inline]
217 fn deref_mut(&mut self) -> &mut StructureRef {
218 unsafe { &mut *(self.0.as_ptr() as *mut StructureRef) }
219 }
220}
221
222impl AsRef<StructureRef> for Structure {
223 #[inline]
224 fn as_ref(&self) -> &StructureRef {
225 self.deref()
226 }
227}
228
229impl AsMut<StructureRef> for Structure {
230 #[inline]
231 fn as_mut(&mut self) -> &mut StructureRef {
232 self.deref_mut()
233 }
234}
235
236impl Clone for Structure {
237 #[inline]
238 fn clone(&self) -> Self {
239 unsafe {
240 let ptr = ffi::gst_structure_copy(self.0.as_ref());
241 debug_assert!(!ptr.is_null());
242 Structure(ptr::NonNull::new_unchecked(ptr))
243 }
244 }
245}
246
247impl Drop for Structure {
248 #[inline]
249 fn drop(&mut self) {
250 unsafe { ffi::gst_structure_free(self.0.as_mut()) }
251 }
252}
253
254impl fmt::Debug for Structure {
255 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256 f.debug_tuple("Structure").field(self.as_ref()).finish()
257 }
258}
259
260impl fmt::Display for Structure {
261 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
262 f.write_str(&StructureRef::to_string(self.as_ref()))
265 }
266}
267
268impl PartialEq for Structure {
269 fn eq(&self, other: &Structure) -> bool {
270 StructureRef::eq(self, other)
271 }
272}
273
274impl Eq for Structure {}
275
276impl PartialEq<StructureRef> for Structure {
277 fn eq(&self, other: &StructureRef) -> bool {
278 StructureRef::eq(self, other)
279 }
280}
281
282impl PartialEq<Structure> for StructureRef {
283 fn eq(&self, other: &Structure) -> bool {
284 StructureRef::eq(other, self)
285 }
286}
287
288impl str::FromStr for Structure {
289 type Err = glib::BoolError;
290
291 #[doc(alias = "gst_structure_from_string")]
292 fn from_str(s: &str) -> Result<Self, Self::Err> {
293 assert_initialized_main_thread!();
294 unsafe {
295 let structure =
296 s.run_with_gstr(|s| ffi::gst_structure_from_string(s.as_ptr(), ptr::null_mut()));
297 if structure.is_null() {
298 Err(glib::bool_error!("Failed to parse structure from string"))
299 } else {
300 Ok(Self(ptr::NonNull::new_unchecked(structure)))
301 }
302 }
303 }
304}
305
306impl Borrow<StructureRef> for Structure {
307 #[inline]
308 fn borrow(&self) -> &StructureRef {
309 self.as_ref()
310 }
311}
312
313impl BorrowMut<StructureRef> for Structure {
314 #[inline]
315 fn borrow_mut(&mut self) -> &mut StructureRef {
316 self.as_mut()
317 }
318}
319
320impl ToOwned for StructureRef {
321 type Owned = Structure;
322
323 fn to_owned(&self) -> Structure {
324 unsafe {
325 let ptr = ffi::gst_structure_copy(&self.0);
326 debug_assert!(!ptr.is_null());
327 Structure(ptr::NonNull::new_unchecked(ptr))
328 }
329 }
330}
331
332impl glib::types::StaticType for Structure {
333 #[inline]
334 fn static_type() -> glib::types::Type {
335 unsafe { from_glib(ffi::gst_structure_get_type()) }
336 }
337}
338
339impl<'a> ToGlibPtr<'a, *const ffi::GstStructure> for Structure {
340 type Storage = PhantomData<&'a Self>;
341
342 #[inline]
343 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GstStructure, Self> {
344 unsafe { Stash(self.0.as_ref(), PhantomData) }
345 }
346
347 #[inline]
348 fn to_glib_full(&self) -> *const ffi::GstStructure {
349 unsafe { ffi::gst_structure_copy(self.0.as_ref()) }
350 }
351}
352
353impl<'a> ToGlibPtr<'a, *mut ffi::GstStructure> for Structure {
354 type Storage = PhantomData<&'a Self>;
355
356 #[inline]
357 fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GstStructure, Self> {
358 unsafe {
359 Stash(
360 self.0.as_ref() as *const ffi::GstStructure as *mut ffi::GstStructure,
361 PhantomData,
362 )
363 }
364 }
365
366 #[inline]
367 fn to_glib_full(&self) -> *mut ffi::GstStructure {
368 unsafe { ffi::gst_structure_copy(self.0.as_ref()) }
369 }
370}
371
372impl<'a> ToGlibPtrMut<'a, *mut ffi::GstStructure> for Structure {
373 type Storage = PhantomData<&'a mut Self>;
374
375 #[inline]
376 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GstStructure, Self> {
377 unsafe { StashMut(self.0.as_mut(), PhantomData) }
378 }
379}
380
381impl FromGlibPtrNone<*const ffi::GstStructure> for Structure {
382 #[inline]
383 unsafe fn from_glib_none(ptr: *const ffi::GstStructure) -> Self {
384 debug_assert!(!ptr.is_null());
385 let ptr = ffi::gst_structure_copy(ptr);
386 debug_assert!(!ptr.is_null());
387 Structure(ptr::NonNull::new_unchecked(ptr))
388 }
389}
390
391impl FromGlibPtrNone<*mut ffi::GstStructure> for Structure {
392 #[inline]
393 unsafe fn from_glib_none(ptr: *mut ffi::GstStructure) -> Self {
394 debug_assert!(!ptr.is_null());
395 let ptr = ffi::gst_structure_copy(ptr);
396 debug_assert!(!ptr.is_null());
397 Structure(ptr::NonNull::new_unchecked(ptr))
398 }
399}
400
401impl FromGlibPtrFull<*const ffi::GstStructure> for Structure {
402 #[inline]
403 unsafe fn from_glib_full(ptr: *const ffi::GstStructure) -> Self {
404 debug_assert!(!ptr.is_null());
405 Structure(ptr::NonNull::new_unchecked(ptr as *mut ffi::GstStructure))
406 }
407}
408
409impl FromGlibPtrFull<*mut ffi::GstStructure> for Structure {
410 #[inline]
411 unsafe fn from_glib_full(ptr: *mut ffi::GstStructure) -> Self {
412 debug_assert!(!ptr.is_null());
413 Structure(ptr::NonNull::new_unchecked(ptr))
414 }
415}
416
417impl FromGlibPtrBorrow<*const ffi::GstStructure> for Structure {
418 #[inline]
419 unsafe fn from_glib_borrow(ptr: *const ffi::GstStructure) -> Borrowed<Self> {
420 Borrowed::new(from_glib_full(ptr))
421 }
422}
423
424impl FromGlibPtrBorrow<*mut ffi::GstStructure> for Structure {
425 #[inline]
426 unsafe fn from_glib_borrow(ptr: *mut ffi::GstStructure) -> Borrowed<Self> {
427 Borrowed::new(from_glib_full(ptr))
428 }
429}
430
431impl glib::value::ValueType for Structure {
432 type Type = Self;
433}
434
435impl glib::value::ValueTypeOptional for Structure {}
436
437unsafe impl<'a> glib::value::FromValue<'a> for Structure {
438 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
439
440 unsafe fn from_value(value: &'a glib::Value) -> Self {
441 skip_assert_initialized!();
442 from_glib_none(
443 glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstStructure
444 )
445 }
446}
447
448impl glib::value::ToValue for Structure {
449 fn to_value(&self) -> glib::Value {
450 let mut value = glib::Value::for_value_type::<Self>();
451 unsafe {
452 glib::gobject_ffi::g_value_set_boxed(
453 value.to_glib_none_mut().0,
454 glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(self).0
455 as *mut _,
456 )
457 }
458 value
459 }
460
461 fn value_type(&self) -> glib::Type {
462 Self::static_type()
463 }
464}
465
466impl glib::value::ToValueOptional for Structure {
467 fn to_value_optional(s: Option<&Self>) -> glib::Value {
468 skip_assert_initialized!();
469 let mut value = glib::Value::for_value_type::<Self>();
470 unsafe {
471 glib::gobject_ffi::g_value_set_boxed(
472 value.to_glib_none_mut().0,
473 glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(&s).0
474 as *mut _,
475 )
476 }
477 value
478 }
479}
480
481impl From<Structure> for glib::Value {
482 fn from(v: Structure) -> glib::Value {
483 skip_assert_initialized!();
484 let mut value = glib::Value::for_value_type::<Structure>();
485 unsafe {
486 glib::gobject_ffi::g_value_take_boxed(
487 value.to_glib_none_mut().0,
488 glib::translate::IntoGlibPtr::<*mut ffi::GstStructure>::into_glib_ptr(v) as *mut _,
489 )
490 }
491 value
492 }
493}
494
495impl GlibPtrDefault for Structure {
496 type GlibType = *mut ffi::GstStructure;
497}
498
499unsafe impl TransparentPtrType for Structure {}
500
501#[repr(transparent)]
502#[doc(alias = "GstStructure")]
503pub struct StructureRef(ffi::GstStructure);
504
505unsafe impl Send for StructureRef {}
506unsafe impl Sync for StructureRef {}
507
508impl StructureRef {
509 #[inline]
510 pub unsafe fn from_glib_borrow<'a>(ptr: *const ffi::GstStructure) -> &'a StructureRef {
511 debug_assert!(!ptr.is_null());
512
513 &*(ptr as *mut StructureRef)
514 }
515
516 #[inline]
517 pub unsafe fn from_glib_borrow_mut<'a>(ptr: *mut ffi::GstStructure) -> &'a mut StructureRef {
518 debug_assert!(!ptr.is_null());
519
520 &mut *(ptr as *mut StructureRef)
521 }
522
523 #[inline]
524 pub fn as_ptr(&self) -> *const ffi::GstStructure {
525 self as *const Self as *const ffi::GstStructure
526 }
527
528 #[inline]
529 pub fn as_mut_ptr(&self) -> *mut ffi::GstStructure {
530 self as *const Self as *mut ffi::GstStructure
531 }
532
533 #[doc(alias = "gst_structure_get")]
534 pub fn get<'a, T: FromValue<'a>>(
535 &'a self,
536 name: impl IntoGStr,
537 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
538 {
539 let name = glib::Quark::from_str(name);
540 self.get_by_quark(name)
541 }
542
543 #[doc(alias = "gst_structure_get")]
544 pub fn get_optional<'a, T: FromValue<'a>>(
545 &'a self,
546 name: impl IntoGStr,
547 ) -> Result<
548 Option<T>,
549 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
550 > {
551 let name = glib::Quark::from_str(name);
552 self.get_optional_by_quark(name)
553 }
554
555 #[doc(alias = "get_value")]
556 #[doc(alias = "gst_structure_get_value")]
557 pub fn value(
558 &self,
559 name: impl IntoGStr,
560 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
561 let name = glib::Quark::from_str(name);
562 self.value_by_quark(name)
563 }
564
565 #[doc(alias = "gst_structure_id_get")]
566 pub fn get_by_quark<'a, T: FromValue<'a>>(
567 &'a self,
568 name: glib::Quark,
569 ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
570 {
571 self.value_by_quark(name)
572 .map_err(|err| match err {
573 GetError::FieldNotFound { name } => GetError::FieldNotFound { name },
574 _ => unreachable!(),
575 })?
576 .get()
577 .map_err(|err| GetError::from_value_get_error(name.as_str(), err))
578 }
579
580 #[doc(alias = "gst_structure_id_get")]
581 pub fn get_optional_by_quark<'a, T: FromValue<'a>>(
582 &'a self,
583 name: glib::Quark,
584 ) -> Result<
585 Option<T>,
586 GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
587 > {
588 self.value_by_quark(name)
589 .ok()
590 .map(|v| v.get())
591 .transpose()
592 .map_err(|err| GetError::from_value_get_error(name.as_str(), err))
593 }
594
595 #[doc(alias = "gst_structure_id_get_value")]
596 pub fn value_by_quark(
597 &self,
598 name: glib::Quark,
599 ) -> Result<&SendValue, GetError<std::convert::Infallible>> {
600 unsafe {
601 let value = ffi::gst_structure_id_get_value(&self.0, name.into_glib());
602
603 if value.is_null() {
604 return Err(GetError::new_field_not_found(name.as_str()));
605 }
606
607 Ok(&*(value as *const SendValue))
608 }
609 }
610
611 #[doc(alias = "gst_structure_set")]
616 pub fn set(&mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) {
617 let value = glib::SendValue::from_owned(value);
618 self.set_value(name, value);
619 }
620
621 #[doc(alias = "gst_structure_set")]
627 pub fn set_if(
628 &mut self,
629 name: impl IntoGStr,
630 value: impl Into<glib::Value> + Send,
631 predicate: bool,
632 ) {
633 if predicate {
634 self.set(name, value);
635 }
636 }
637
638 #[doc(alias = "gst_structure_set")]
643 pub fn set_if_some(
644 &mut self,
645 name: impl IntoGStr,
646 value: Option<impl Into<glib::Value> + Send>,
647 ) {
648 if let Some(value) = value {
649 self.set(name, value);
650 }
651 }
652
653 #[inline]
658 pub fn set_from_iter<V: ValueType + Into<Value> + FromIterator<SendValue> + Send>(
659 &mut self,
660 name: impl IntoGStr,
661 iter: impl IntoIterator<Item = impl ToSendValue>,
662 ) {
663 let iter = iter.into_iter().map(|item| item.to_send_value());
664 self.set(name, V::from_iter(iter));
665 }
666
667 #[inline]
673 pub fn set_if_not_empty<V: ValueType + Into<Value> + FromIterator<SendValue> + Send>(
674 &mut self,
675 name: impl IntoGStr,
676 iter: impl IntoIterator<Item = impl ToSendValue>,
677 ) {
678 let mut iter = iter.into_iter().peekable();
679 if iter.peek().is_some() {
680 let iter = iter.map(|item| item.to_send_value());
681 self.set(name, V::from_iter(iter));
682 }
683 }
684
685 #[doc(alias = "gst_structure_set_value")]
690 pub fn set_value(&mut self, name: impl IntoGStr, value: SendValue) {
691 unsafe {
692 name.run_with_gstr(|name| {
693 ffi::gst_structure_take_value(&mut self.0, name.as_ptr(), &mut value.into_raw())
694 });
695 }
696 }
697
698 #[doc(alias = "gst_structure_set_value")]
704 pub fn set_value_if(&mut self, name: impl IntoGStr, value: SendValue, predicate: bool) {
705 if predicate {
706 self.set_value(name, value);
707 }
708 }
709
710 #[doc(alias = "gst_structure_set_value")]
715 pub fn set_value_if_some(&mut self, name: impl IntoGStr, value: Option<SendValue>) {
716 if let Some(value) = value {
717 self.set_value(name, value);
718 }
719 }
720
721 #[doc(alias = "gst_structure_id_set")]
722 pub fn set_by_quark(&mut self, name: glib::Quark, value: impl Into<glib::Value> + Send) {
723 let value = glib::SendValue::from_owned(value);
724 self.set_value_by_quark(name, value);
725 }
726
727 #[doc(alias = "gst_structure_id_set")]
728 pub fn set_by_quark_if_some(
729 &mut self,
730 name: glib::Quark,
731 value: Option<impl Into<glib::Value> + Send>,
732 ) {
733 if let Some(value) = value {
734 self.set_by_quark(name, value);
735 }
736 }
737
738 #[doc(alias = "gst_structure_id_set_value")]
739 pub fn set_value_by_quark(&mut self, name: glib::Quark, value: SendValue) {
740 unsafe {
741 ffi::gst_structure_id_take_value(&mut self.0, name.into_glib(), &mut value.into_raw());
742 }
743 }
744
745 #[doc(alias = "gst_structure_id_set_value")]
746 pub fn set_value_by_quark_if_some(&mut self, name: glib::Quark, value: Option<SendValue>) {
747 if let Some(value) = value {
748 self.set_value_by_quark(name, value);
749 }
750 }
751
752 #[doc(alias = "get_name")]
753 #[doc(alias = "gst_structure_get_name")]
754 pub fn name<'a>(&self) -> &'a glib::GStr {
755 unsafe {
756 let name = ffi::gst_structure_get_name(&self.0);
757 glib::GStr::from_ptr(glib::ffi::g_intern_string(name))
759 }
760 }
761
762 #[doc(alias = "gst_structure_get_name_id")]
763 pub fn name_quark(&self) -> glib::Quark {
764 unsafe { from_glib(ffi::gst_structure_get_name_id(&self.0)) }
765 }
766
767 #[doc(alias = "gst_structure_set_name")]
768 pub fn set_name(&mut self, name: impl IntoGStr) {
769 unsafe {
770 name.run_with_gstr(|name| ffi::gst_structure_set_name(&mut self.0, name.as_ptr()))
771 }
772 }
773
774 #[doc(alias = "gst_structure_set_name")]
775 pub fn set_name_if_some(&mut self, name: Option<impl IntoGStr>) {
776 if let Some(name) = name {
777 self.set_name(name);
778 }
779 }
780
781 #[doc(alias = "gst_structure_has_name")]
782 pub fn has_name(&self, name: &str) -> bool {
783 self.name() == name
784 }
785
786 #[doc(alias = "gst_structure_has_field")]
787 pub fn has_field(&self, field: impl IntoGStr) -> bool {
788 unsafe {
789 field.run_with_gstr(|field| {
790 from_glib(ffi::gst_structure_has_field(&self.0, field.as_ptr()))
791 })
792 }
793 }
794
795 #[doc(alias = "gst_structure_has_field_typed")]
796 pub fn has_field_with_type(&self, field: impl IntoGStr, type_: glib::Type) -> bool {
797 unsafe {
798 field.run_with_gstr(|field| {
799 from_glib(ffi::gst_structure_has_field_typed(
800 &self.0,
801 field.as_ptr(),
802 type_.into_glib(),
803 ))
804 })
805 }
806 }
807
808 #[doc(alias = "gst_structure_id_has_field")]
809 pub fn has_field_by_quark(&self, field: glib::Quark) -> bool {
810 unsafe { from_glib(ffi::gst_structure_id_has_field(&self.0, field.into_glib())) }
811 }
812
813 #[doc(alias = "gst_structure_id_has_field_typed")]
814 pub fn has_field_with_type_by_quark(&self, field: glib::Quark, type_: glib::Type) -> bool {
815 unsafe {
816 from_glib(ffi::gst_structure_id_has_field_typed(
817 &self.0,
818 field.into_glib(),
819 type_.into_glib(),
820 ))
821 }
822 }
823
824 #[doc(alias = "gst_structure_remove_field")]
825 pub fn remove_field(&mut self, field: impl IntoGStr) {
826 unsafe {
827 field.run_with_gstr(|field| {
828 ffi::gst_structure_remove_field(&mut self.0, field.as_ptr())
829 });
830 }
831 }
832
833 #[doc(alias = "gst_structure_remove_fields")]
834 pub fn remove_fields(&mut self, fields: impl IntoIterator<Item = impl IntoGStr>) {
835 for f in fields.into_iter() {
836 self.remove_field(f)
837 }
838 }
839
840 #[doc(alias = "gst_structure_remove_all_fields")]
841 pub fn remove_all_fields(&mut self) {
842 unsafe {
843 ffi::gst_structure_remove_all_fields(&mut self.0);
844 }
845 }
846
847 pub fn fields(&self) -> FieldIterator {
848 FieldIterator::new(self)
849 }
850
851 pub fn iter(&self) -> Iter {
852 Iter::new(self)
853 }
854
855 #[doc(alias = "get_nth_field_name")]
856 #[doc(alias = "gst_structure_nth_field_name")]
857 pub fn nth_field_name<'a>(&self, idx: usize) -> Option<&'a glib::GStr> {
858 if idx >= self.n_fields() {
859 return None;
860 }
861
862 unsafe {
863 let field_name = ffi::gst_structure_nth_field_name(&self.0, idx as u32);
864 debug_assert!(!field_name.is_null());
865
866 Some(glib::GStr::from_ptr(glib::ffi::g_intern_string(field_name)))
868 }
869 }
870
871 #[doc(alias = "gst_structure_n_fields")]
872 pub fn n_fields(&self) -> usize {
873 unsafe { ffi::gst_structure_n_fields(&self.0) as usize }
874 }
875
876 pub fn len(&self) -> usize {
877 self.n_fields()
878 }
879
880 pub fn is_empty(&self) -> bool {
881 self.n_fields() == 0
882 }
883
884 #[doc(alias = "gst_structure_can_intersect")]
885 pub fn can_intersect(&self, other: &StructureRef) -> bool {
886 unsafe { from_glib(ffi::gst_structure_can_intersect(&self.0, &other.0)) }
887 }
888
889 #[doc(alias = "gst_structure_intersect")]
890 pub fn intersect(&self, other: &StructureRef) -> Option<Structure> {
891 unsafe { from_glib_full(ffi::gst_structure_intersect(&self.0, &other.0)) }
892 }
893
894 #[doc(alias = "gst_structure_is_subset")]
895 pub fn is_subset(&self, superset: &StructureRef) -> bool {
896 unsafe { from_glib(ffi::gst_structure_is_subset(&self.0, &superset.0)) }
897 }
898
899 #[doc(alias = "gst_structure_fixate")]
900 pub fn fixate(&mut self) {
901 unsafe { ffi::gst_structure_fixate(&mut self.0) }
902 }
903
904 #[doc(alias = "gst_structure_fixate_field")]
905 pub fn fixate_field(&mut self, name: impl IntoGStr) -> bool {
906 unsafe {
907 name.run_with_gstr(|name| {
908 from_glib(ffi::gst_structure_fixate_field(&mut self.0, name.as_ptr()))
909 })
910 }
911 }
912
913 #[doc(alias = "gst_structure_fixate_field_boolean")]
914 pub fn fixate_field_bool(&mut self, name: impl IntoGStr, target: bool) -> bool {
915 unsafe {
916 name.run_with_gstr(|name| {
917 from_glib(ffi::gst_structure_fixate_field_boolean(
918 &mut self.0,
919 name.as_ptr(),
920 target.into_glib(),
921 ))
922 })
923 }
924 }
925
926 #[doc(alias = "gst_structure_fixate_field_string")]
927 pub fn fixate_field_str(&mut self, name: impl IntoGStr, target: impl IntoGStr) -> bool {
928 unsafe {
929 name.run_with_gstr(|name| {
930 target.run_with_gstr(|target| {
931 from_glib(ffi::gst_structure_fixate_field_string(
932 &mut self.0,
933 name.as_ptr(),
934 target.as_ptr(),
935 ))
936 })
937 })
938 }
939 }
940
941 #[doc(alias = "gst_structure_fixate_field_nearest_double")]
942 pub fn fixate_field_nearest_double(&mut self, name: impl IntoGStr, target: f64) -> bool {
943 unsafe {
944 name.run_with_gstr(|name| {
945 from_glib(ffi::gst_structure_fixate_field_nearest_double(
946 &mut self.0,
947 name.as_ptr(),
948 target,
949 ))
950 })
951 }
952 }
953
954 #[doc(alias = "gst_structure_fixate_field_nearest_fraction")]
955 pub fn fixate_field_nearest_fraction(
956 &mut self,
957 name: impl IntoGStr,
958 target: impl Into<Fraction>,
959 ) -> bool {
960 skip_assert_initialized!();
961
962 let target = target.into();
963 unsafe {
964 name.run_with_gstr(|name| {
965 from_glib(ffi::gst_structure_fixate_field_nearest_fraction(
966 &mut self.0,
967 name.as_ptr(),
968 target.numer(),
969 target.denom(),
970 ))
971 })
972 }
973 }
974
975 #[doc(alias = "gst_structure_fixate_field_nearest_int")]
976 pub fn fixate_field_nearest_int(&mut self, name: impl IntoGStr, target: i32) -> bool {
977 unsafe {
978 name.run_with_gstr(|name| {
979 from_glib(ffi::gst_structure_fixate_field_nearest_int(
980 &mut self.0,
981 name.as_ptr(),
982 target,
983 ))
984 })
985 }
986 }
987
988 #[cfg(feature = "v1_20")]
989 #[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
990 #[doc(alias = "gst_structure_serialize")]
991 pub fn serialize(&self, flags: crate::SerializeFlags) -> glib::GString {
992 unsafe { from_glib_full(ffi::gst_structure_serialize(&self.0, flags.into_glib())) }
993 }
994
995 #[cfg(feature = "v1_24")]
996 #[cfg_attr(docsrs, doc(cfg(feature = "v1_24")))]
997 #[doc(alias = "gst_structure_serialize")]
998 #[doc(alias = "gst_structure_serialize_full")]
999 pub fn serialize_strict(
1000 &self,
1001 flags: crate::SerializeFlags,
1002 ) -> Result<glib::GString, glib::BoolError> {
1003 unsafe {
1004 let res = ffi::gst_structure_serialize_full(
1005 &self.0,
1006 flags.into_glib() | ffi::GST_SERIALIZE_FLAG_STRICT,
1007 );
1008 if res.is_null() {
1009 Err(glib::bool_error!("Failed to serialize structure to string"))
1010 } else {
1011 Ok(from_glib_full(res))
1012 }
1013 }
1014 }
1015
1016 #[doc(alias = "gst_structure_foreach")]
1017 pub fn foreach<F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>>(
1018 &self,
1019 mut func: F,
1020 ) -> bool {
1021 unsafe {
1022 unsafe extern "C" fn trampoline<
1023 F: FnMut(glib::Quark, &glib::Value) -> std::ops::ControlFlow<()>,
1024 >(
1025 quark: glib::ffi::GQuark,
1026 value: *const glib::gobject_ffi::GValue,
1027 user_data: glib::ffi::gpointer,
1028 ) -> glib::ffi::gboolean {
1029 let func = &mut *(user_data as *mut F);
1030 let res = func(from_glib(quark), &*(value as *const glib::Value));
1031
1032 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1033 }
1034 let func = &mut func as *mut F;
1035 from_glib(ffi::gst_structure_foreach(
1036 self.as_ptr(),
1037 Some(trampoline::<F>),
1038 func as glib::ffi::gpointer,
1039 ))
1040 }
1041 }
1042
1043 #[doc(alias = "gst_structure_map_in_place")]
1044 pub fn map_in_place<F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>>(
1045 &mut self,
1046 mut func: F,
1047 ) -> bool {
1048 unsafe {
1049 unsafe extern "C" fn trampoline<
1050 F: FnMut(glib::Quark, &mut glib::Value) -> std::ops::ControlFlow<()>,
1051 >(
1052 quark: glib::ffi::GQuark,
1053 value: *mut glib::gobject_ffi::GValue,
1054 user_data: glib::ffi::gpointer,
1055 ) -> glib::ffi::gboolean {
1056 let func = &mut *(user_data as *mut F);
1057 let res = func(from_glib(quark), &mut *(value as *mut glib::Value));
1058
1059 matches!(res, std::ops::ControlFlow::Continue(_)).into_glib()
1060 }
1061 let func = &mut func as *mut F;
1062 from_glib(ffi::gst_structure_map_in_place(
1063 self.as_mut_ptr(),
1064 Some(trampoline::<F>),
1065 func as glib::ffi::gpointer,
1066 ))
1067 }
1068 }
1069
1070 #[doc(alias = "gst_structure_filter_and_map_in_place")]
1071 pub fn filter_map_in_place<F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>>(
1072 &mut self,
1073 mut func: F,
1074 ) {
1075 unsafe {
1076 unsafe extern "C" fn trampoline<
1077 F: FnMut(glib::Quark, glib::Value) -> Option<glib::Value>,
1078 >(
1079 quark: glib::ffi::GQuark,
1080 value: *mut glib::gobject_ffi::GValue,
1081 user_data: glib::ffi::gpointer,
1082 ) -> glib::ffi::gboolean {
1083 let func = &mut *(user_data as *mut F);
1084
1085 let v = mem::replace(
1086 &mut *(value as *mut glib::Value),
1087 glib::Value::uninitialized(),
1088 );
1089 match func(from_glib(quark), v) {
1090 None => glib::ffi::GFALSE,
1091 Some(v) => {
1092 *value = v.into_raw();
1093 glib::ffi::GTRUE
1094 }
1095 }
1096 }
1097
1098 let func = &mut func as *mut F;
1099 ffi::gst_structure_filter_and_map_in_place(
1100 self.as_mut_ptr(),
1101 Some(trampoline::<F>),
1102 func as glib::ffi::gpointer,
1103 );
1104 }
1105 }
1106}
1107
1108impl fmt::Display for StructureRef {
1109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1110 let s = unsafe { glib::GString::from_glib_full(ffi::gst_structure_to_string(&self.0)) };
1111 f.write_str(&s)
1112 }
1113}
1114
1115impl fmt::Debug for StructureRef {
1116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1117 let mut debug = f.debug_struct(self.name());
1118
1119 for (id, field) in self.iter() {
1120 if field.type_() == Structure::static_type() {
1121 let s = field.get::<Structure>().unwrap();
1122 debug.field(id, &s);
1123 } else if field.type_() == crate::Array::static_type() {
1124 let arr = field.get::<crate::Array>().unwrap();
1125 debug.field(id, &arr);
1126 } else if field.type_() == crate::List::static_type() {
1127 let list = field.get::<crate::List>().unwrap();
1128 debug.field(id, &list);
1129 } else {
1130 debug.field(id, &field);
1131 }
1132 }
1133
1134 debug.finish()
1135 }
1136}
1137
1138impl PartialEq for StructureRef {
1139 #[doc(alias = "gst_structure_is_equal")]
1140 fn eq(&self, other: &StructureRef) -> bool {
1141 unsafe { from_glib(ffi::gst_structure_is_equal(&self.0, &other.0)) }
1142 }
1143}
1144
1145impl Eq for StructureRef {}
1146
1147impl glib::types::StaticType for StructureRef {
1148 #[inline]
1149 fn static_type() -> glib::types::Type {
1150 unsafe { from_glib(ffi::gst_structure_get_type()) }
1151 }
1152}
1153
1154unsafe impl<'a> glib::value::FromValue<'a> for &'a StructureRef {
1155 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
1156
1157 unsafe fn from_value(value: &'a glib::Value) -> Self {
1158 skip_assert_initialized!();
1159 &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const StructureRef)
1160 }
1161}
1162
1163impl glib::value::ToValue for StructureRef {
1164 fn to_value(&self) -> glib::Value {
1165 let mut value = glib::Value::for_value_type::<Structure>();
1166 unsafe {
1167 glib::gobject_ffi::g_value_set_boxed(
1168 value.to_glib_none_mut().0,
1169 self.as_ptr() as *mut _,
1170 )
1171 }
1172 value
1173 }
1174
1175 fn value_type(&self) -> glib::Type {
1176 Self::static_type()
1177 }
1178}
1179
1180impl glib::value::ToValueOptional for StructureRef {
1181 fn to_value_optional(s: Option<&Self>) -> glib::Value {
1182 skip_assert_initialized!();
1183 let mut value = glib::Value::for_value_type::<Structure>();
1184 unsafe {
1185 glib::gobject_ffi::g_value_set_boxed(
1186 value.to_glib_none_mut().0,
1187 s.map(|s| s.as_ptr()).unwrap_or(ptr::null()) as *mut _,
1188 )
1189 }
1190 value
1191 }
1192}
1193
1194#[derive(Debug)]
1195pub struct FieldIterator<'a> {
1196 structure: &'a StructureRef,
1197 idx: usize,
1198 n_fields: usize,
1199}
1200
1201impl<'a> FieldIterator<'a> {
1202 fn new(structure: &'a StructureRef) -> FieldIterator<'a> {
1203 skip_assert_initialized!();
1204 let n_fields = structure.n_fields();
1205
1206 FieldIterator {
1207 structure,
1208 idx: 0,
1209 n_fields,
1210 }
1211 }
1212}
1213
1214impl Iterator for FieldIterator<'_> {
1215 type Item = &'static glib::GStr;
1216
1217 fn next(&mut self) -> Option<Self::Item> {
1218 if self.idx >= self.n_fields {
1219 return None;
1220 }
1221
1222 let field_name = self.structure.nth_field_name(self.idx).unwrap();
1225 self.idx += 1;
1226
1227 Some(field_name)
1228 }
1229
1230 fn size_hint(&self) -> (usize, Option<usize>) {
1231 let remaining = self.n_fields - self.idx;
1232
1233 (remaining, Some(remaining))
1234 }
1235}
1236
1237impl DoubleEndedIterator for FieldIterator<'_> {
1238 fn next_back(&mut self) -> Option<Self::Item> {
1239 if self.idx == self.n_fields {
1240 return None;
1241 }
1242
1243 self.n_fields -= 1;
1244 Some(self.structure.nth_field_name(self.n_fields).unwrap())
1247 }
1248}
1249
1250impl ExactSizeIterator for FieldIterator<'_> {}
1251
1252impl std::iter::FusedIterator for FieldIterator<'_> {}
1253
1254#[derive(Debug)]
1255pub struct Iter<'a> {
1256 iter: FieldIterator<'a>,
1259}
1260
1261impl<'a> Iter<'a> {
1262 fn new(structure: &'a StructureRef) -> Iter<'a> {
1263 skip_assert_initialized!();
1264 Iter {
1265 iter: FieldIterator::new(structure),
1266 }
1267 }
1268}
1269
1270impl<'a> Iterator for Iter<'a> {
1271 type Item = (&'static glib::GStr, &'a SendValue);
1272
1273 fn next(&mut self) -> Option<Self::Item> {
1274 let f = self.iter.next()?;
1275 let v = self.iter.structure.value(f);
1276 Some((f, v.unwrap()))
1277 }
1278
1279 fn size_hint(&self) -> (usize, Option<usize>) {
1280 self.iter.size_hint()
1281 }
1282
1283 fn count(self) -> usize {
1284 self.iter.count()
1285 }
1286
1287 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1288 let f = self.iter.nth(n)?;
1289 let v = self.iter.structure.value(f);
1290 Some((f, v.unwrap()))
1291 }
1292
1293 fn last(self) -> Option<Self::Item> {
1294 let structure = self.iter.structure;
1295 let f = self.iter.last()?;
1296 let v = structure.value(f);
1297 Some((f, v.unwrap()))
1298 }
1299}
1300
1301impl DoubleEndedIterator for Iter<'_> {
1302 fn next_back(&mut self) -> Option<Self::Item> {
1303 let f = self.iter.next_back()?;
1304 let v = self.iter.structure.value(f);
1305 Some((f, v.unwrap()))
1306 }
1307
1308 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1309 let f = self.iter.nth_back(n)?;
1310 let v = self.iter.structure.value(f);
1311 Some((f, v.unwrap()))
1312 }
1313}
1314
1315impl ExactSizeIterator for Iter<'_> {}
1316
1317impl std::iter::FusedIterator for Iter<'_> {}
1318
1319impl<'a> IntoIterator for &'a StructureRef {
1320 type IntoIter = Iter<'a>;
1321 type Item = (&'static glib::GStr, &'a SendValue);
1322
1323 fn into_iter(self) -> Self::IntoIter {
1324 self.iter()
1325 }
1326}
1327
1328impl<'a> std::iter::Extend<(&'a str, SendValue)> for StructureRef {
1329 fn extend<T: IntoIterator<Item = (&'a str, SendValue)>>(&mut self, iter: T) {
1330 iter.into_iter().for_each(|(f, v)| self.set_value(f, v));
1331 }
1332}
1333
1334impl<'a> std::iter::Extend<(&'a glib::GStr, SendValue)> for StructureRef {
1335 fn extend<T: IntoIterator<Item = (&'a glib::GStr, SendValue)>>(&mut self, iter: T) {
1336 iter.into_iter().for_each(|(f, v)| self.set_value(f, v));
1337 }
1338}
1339
1340impl std::iter::Extend<(String, SendValue)> for StructureRef {
1341 fn extend<T: IntoIterator<Item = (String, SendValue)>>(&mut self, iter: T) {
1342 iter.into_iter().for_each(|(f, v)| self.set_value(&f, v));
1343 }
1344}
1345
1346impl std::iter::Extend<(glib::GString, SendValue)> for StructureRef {
1347 fn extend<T: IntoIterator<Item = (glib::GString, SendValue)>>(&mut self, iter: T) {
1348 iter.into_iter().for_each(|(f, v)| self.set_value(&f, v));
1349 }
1350}
1351
1352impl std::iter::Extend<(glib::Quark, SendValue)> for StructureRef {
1353 fn extend<T: IntoIterator<Item = (glib::Quark, SendValue)>>(&mut self, iter: T) {
1354 iter.into_iter()
1355 .for_each(|(f, v)| self.set_value_by_quark(f, v));
1356 }
1357}
1358
1359#[derive(Debug)]
1360#[must_use = "The builder must be built to be used"]
1361pub struct Builder {
1362 s: Structure,
1363}
1364
1365impl Builder {
1366 fn new(name: impl IntoGStr) -> Self {
1367 skip_assert_initialized!();
1368 Builder {
1369 s: Structure::new_empty(name),
1370 }
1371 }
1372
1373 #[inline]
1378 pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self {
1379 self.s.set(name, value);
1380 self
1381 }
1382
1383 impl_builder_gvalue_extra_setters!(field);
1384
1385 #[must_use = "Building the structure without using it has no effect"]
1386 pub fn build(self) -> Structure {
1387 self.s
1388 }
1389}
1390
1391#[cfg(test)]
1392mod tests {
1393 use super::*;
1394
1395 #[test]
1396 fn new_set_get() {
1397 use glib::{value, Type};
1398
1399 crate::init().unwrap();
1400
1401 let mut s = Structure::new_empty("test");
1402 assert_eq!(s.name(), "test");
1403
1404 s.set("f1", "abc");
1405 s.set("f2", String::from("bcd"));
1406 s.set("f3", 123i32);
1407 s.set("f5", Some("efg"));
1408 s.set("f7", 42i32);
1409
1410 assert_eq!(s.get::<&str>("f1"), Ok("abc"));
1411 assert_eq!(s.get::<Option<&str>>("f2"), Ok(Some("bcd")));
1412 assert_eq!(s.get::<i32>("f3"), Ok(123i32));
1413 assert_eq!(s.get_optional::<&str>("f1"), Ok(Some("abc")));
1414 assert_eq!(s.get_optional::<&str>("f4"), Ok(None));
1415 assert_eq!(s.get_optional::<i32>("f3"), Ok(Some(123i32)));
1416 assert_eq!(s.get_optional::<i32>("f4"), Ok(None));
1417 assert_eq!(s.get::<&str>("f5"), Ok("efg"));
1418 assert_eq!(s.get::<i32>("f7"), Ok(42i32));
1419
1420 assert_eq!(
1421 s.get::<i32>("f2"),
1422 Err(GetError::from_value_get_error(
1423 "f2",
1424 value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
1425 ))
1426 );
1427 assert_eq!(
1428 s.get::<bool>("f3"),
1429 Err(GetError::from_value_get_error(
1430 "f3",
1431 value::ValueTypeMismatchError::new(Type::I32, Type::BOOL),
1432 ))
1433 );
1434 assert_eq!(
1435 s.get::<&str>("f4"),
1436 Err(GetError::new_field_not_found("f4"))
1437 );
1438 assert_eq!(s.get::<i32>("f4"), Err(GetError::new_field_not_found("f4")));
1439
1440 assert_eq!(
1441 s.fields().collect::<Vec<_>>(),
1442 vec!["f1", "f2", "f3", "f5", "f7"]
1443 );
1444
1445 let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>();
1446 assert_eq!(v.len(), 5);
1447 assert_eq!(v[0].0, "f1");
1448 assert_eq!(v[0].1.get::<&str>(), Ok("abc"));
1449 assert_eq!(v[1].0, "f2");
1450 assert_eq!(v[1].1.get::<&str>(), Ok("bcd"));
1451 assert_eq!(v[2].0, "f3");
1452 assert_eq!(v[2].1.get::<i32>(), Ok(123i32));
1453 assert_eq!(v[3].0, "f5");
1454 assert_eq!(v[3].1.get::<&str>(), Ok("efg"));
1455 assert_eq!(v[4].0, "f7");
1456 assert_eq!(v[4].1.get::<i32>(), Ok(42i32));
1457
1458 let s2 = Structure::builder("test")
1459 .field("f1", "abc")
1460 .field("f2", String::from("bcd"))
1461 .field("f3", 123i32)
1462 .field_if_some("f4", Option::<i32>::None)
1463 .field_if_some("f5", Some("efg"))
1464 .field_if_some("f6", Option::<&str>::None)
1465 .field_if("f7", 42i32, true)
1466 .field_if("f8", 21i32, false)
1467 .build();
1468 assert_eq!(s, s2);
1469
1470 let mut s3 = Structure::new_empty("test");
1471
1472 s3.set_if_some("f1", Some("abc"));
1473 s3.set_if_some("f2", Some(String::from("bcd")));
1474 s3.set_if_some("f3", Some(123i32));
1475 s3.set_if_some("f4", Option::<i32>::None);
1476 s3.set_if_some("f5", Some("efg"));
1477 s3.set_if_some("f6", Option::<&str>::None);
1478 s3.set_if("f7", 42i32, true);
1479 s3.set_if("f8", 21i32, false);
1480 assert_eq!(s, s3);
1481 }
1482
1483 #[test]
1484 fn test_string_conversion() {
1485 crate::init().unwrap();
1486
1487 let a = "Test, f1=(string)abc, f2=(uint)123;";
1488
1489 let s = a.parse::<Structure>().unwrap();
1490 assert_eq!(s.get::<&str>("f1"), Ok("abc"));
1491 assert_eq!(s.get::<u32>("f2"), Ok(123));
1492
1493 assert_eq!(a, s.to_string());
1494 }
1495
1496 #[test]
1497 fn test_from_value_optional() {
1498 use glib::value::ToValue;
1499
1500 crate::init().unwrap();
1501
1502 let a = None::<&Structure>.to_value();
1503 assert!(a.get::<Option<Structure>>().unwrap().is_none());
1504 let b = "foo".parse::<Structure>().unwrap().to_value();
1505 assert!(b.get::<Option<Structure>>().unwrap().is_some());
1506 }
1507
1508 #[test]
1509 fn test_new_from_iter() {
1510 crate::init().unwrap();
1511
1512 let s = Structure::builder("test")
1513 .field("f1", "abc")
1514 .field("f2", String::from("bcd"))
1515 .field("f3", 123i32)
1516 .build();
1517
1518 let s2 = Structure::from_iter(
1519 s.name(),
1520 s.iter()
1521 .filter(|(f, _)| *f == "f1")
1522 .map(|(f, v)| (f, v.clone())),
1523 );
1524
1525 assert_eq!(s2.name(), "test");
1526 assert_eq!(s2.get::<&str>("f1"), Ok("abc"));
1527 assert!(s2.get::<&str>("f2").is_err());
1528 assert!(s2.get::<&str>("f3").is_err());
1529 }
1530
1531 #[test]
1532 fn test_debug() {
1533 crate::init().unwrap();
1534
1535 let s = Structure::builder("test")
1536 .field("f1", "abc")
1537 .field("f2", String::from("bcd"))
1538 .field("f3", 123i32)
1539 .field(
1540 "f4",
1541 Structure::builder("nested").field("badger", true).build(),
1542 )
1543 .field("f5", crate::Array::new(["a", "b", "c"]))
1544 .field("f6", crate::List::new(["d", "e", "f"]))
1545 .build();
1546
1547 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\"]) })");
1548 }
1549
1550 #[test]
1551 fn builder_field_from_iter() {
1552 crate::init().unwrap();
1553
1554 let s = Structure::builder("test")
1555 .field_from_iter::<crate::Array>("array", [&1, &2, &3])
1556 .field_from_iter::<crate::List>("list", [&4, &5, &6])
1557 .build();
1558 assert!(s
1559 .get::<crate::Array>("array")
1560 .unwrap()
1561 .iter()
1562 .map(|val| val.get::<i32>().unwrap())
1563 .eq([1, 2, 3]));
1564 assert!(s
1565 .get::<crate::List>("list")
1566 .unwrap()
1567 .iter()
1568 .map(|val| val.get::<i32>().unwrap())
1569 .eq([4, 5, 6]));
1570
1571 let array = Vec::<i32>::new();
1572 let s = Structure::builder("test")
1573 .field_from_iter::<crate::Array>("array", &array)
1574 .field_from_iter::<crate::List>("list", &array)
1575 .build();
1576 assert!(s.get::<crate::Array>("array").unwrap().as_ref().is_empty());
1577 assert!(s.get::<crate::List>("list").unwrap().as_ref().is_empty());
1578 }
1579
1580 #[test]
1581 fn builder_field_if_not_empty() {
1582 crate::init().unwrap();
1583
1584 let s = Structure::builder("test")
1585 .field_if_not_empty::<crate::Array>("array", [&1, &2, &3])
1586 .field_if_not_empty::<crate::List>("list", [&4, &5, &6])
1587 .build();
1588 assert!(s
1589 .get::<crate::Array>("array")
1590 .unwrap()
1591 .iter()
1592 .map(|val| val.get::<i32>().unwrap())
1593 .eq([1, 2, 3]));
1594 assert!(s
1595 .get::<crate::List>("list")
1596 .unwrap()
1597 .iter()
1598 .map(|val| val.get::<i32>().unwrap())
1599 .eq([4, 5, 6]));
1600
1601 let array = Vec::<i32>::new();
1602 let s = Structure::builder("test")
1603 .field_if_not_empty::<crate::Array>("array", &array)
1604 .field_if_not_empty::<crate::List>("list", &array)
1605 .build();
1606 assert!(!s.has_field("array"));
1607 assert!(!s.has_field("list"));
1608 }
1609
1610 #[test]
1611 fn test_name_and_field_name_lt() {
1612 crate::init().unwrap();
1613
1614 let (name, field_name) = {
1615 let s = Structure::builder("name")
1616 .field("field0", "val0")
1617 .field("field1", "val1")
1618 .build();
1619
1620 (s.name(), s.nth_field_name(0).unwrap())
1621 };
1622
1623 assert_eq!(name, "name");
1624 assert_eq!(field_name, "field0");
1625 }
1626}