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