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