1use std::{
4 borrow::{Borrow, Cow},
5 fmt,
6 hash::{Hash, Hasher},
7 iter,
8 marker::PhantomData,
9 ops::Deref,
10 ptr, slice,
11 str::FromStr,
12};
13
14use crate::{BoolError, Type, ffi, gobject_ffi, prelude::*, translate::*};
15
16#[doc(alias = "GVariantType")]
189pub struct VariantType {
190 ptr: ptr::NonNull<ffi::GVariantType>,
193 len: usize,
196}
197
198impl VariantType {
199 pub fn new(type_string: &str) -> Result<VariantType, BoolError> {
218 VariantTy::new(type_string).map(ToOwned::to_owned)
219 }
220
221 #[doc(alias = "g_variant_type_new_dict_entry")]
238 pub fn new_dict_entry(key_type: &VariantTy, value_type: &VariantTy) -> VariantType {
239 unsafe {
240 from_glib_full(ffi::g_variant_type_new_dict_entry(
241 key_type.to_glib_none().0,
242 value_type.to_glib_none().0,
243 ))
244 }
245 }
246
247 #[doc(alias = "g_variant_type_new_array")]
262 pub fn new_array(elem_type: &VariantTy) -> VariantType {
263 unsafe { from_glib_full(ffi::g_variant_type_new_array(elem_type.to_glib_none().0)) }
264 }
265
266 #[doc(alias = "g_variant_type_new_maybe")]
281 pub fn new_maybe(child_type: &VariantTy) -> VariantType {
282 unsafe { from_glib_full(ffi::g_variant_type_new_maybe(child_type.to_glib_none().0)) }
283 }
284
285 #[doc(alias = "g_variant_type_new_tuple")]
302 pub fn new_tuple(items: impl IntoIterator<Item = impl AsRef<VariantTy>>) -> VariantType {
303 let mut builder = crate::GStringBuilder::new("(");
304
305 for ty in items {
306 builder.append(ty.as_ref().as_str());
307 }
308
309 builder.append_c(')');
310
311 VariantType::from_string(builder.into_string()).unwrap()
312 }
313
314 pub fn from_string(type_string: impl Into<crate::GString>) -> Result<VariantType, BoolError> {
319 let type_string = type_string.into();
320 VariantTy::new(&type_string)?;
321
322 let len = type_string.len();
323 unsafe {
324 let ptr = type_string.into_glib_ptr();
325
326 Ok(VariantType {
327 ptr: ptr::NonNull::new_unchecked(ptr as *mut ffi::GVariantType),
328 len,
329 })
330 }
331 }
332}
333
334unsafe impl Send for VariantType {}
335unsafe impl Sync for VariantType {}
336
337impl Drop for VariantType {
338 #[inline]
339 fn drop(&mut self) {
340 unsafe { ffi::g_variant_type_free(self.ptr.as_ptr()) }
341 }
342}
343
344impl AsRef<VariantTy> for VariantType {
345 #[inline]
346 fn as_ref(&self) -> &VariantTy {
347 self
348 }
349}
350
351impl Borrow<VariantTy> for VariantType {
352 #[inline]
353 fn borrow(&self) -> &VariantTy {
354 self
355 }
356}
357
358impl Clone for VariantType {
359 #[inline]
360 fn clone(&self) -> VariantType {
361 unsafe {
362 VariantType {
363 ptr: ptr::NonNull::new_unchecked(ffi::g_variant_type_copy(self.ptr.as_ptr())),
364 len: self.len,
365 }
366 }
367 }
368}
369
370impl Deref for VariantType {
371 type Target = VariantTy;
372
373 #[allow(clippy::cast_slice_from_raw_parts)]
374 #[inline]
375 fn deref(&self) -> &VariantTy {
376 unsafe {
377 &*(slice::from_raw_parts(self.ptr.as_ptr() as *const u8, self.len) as *const [u8]
378 as *const VariantTy)
379 }
380 }
381}
382
383impl fmt::Debug for VariantType {
384 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
385 <VariantTy as fmt::Debug>::fmt(self, f)
386 }
387}
388
389impl fmt::Display for VariantType {
390 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
391 f.write_str(self.as_str())
392 }
393}
394
395impl FromStr for VariantType {
396 type Err = BoolError;
397
398 fn from_str(s: &str) -> Result<Self, Self::Err> {
399 Self::new(s)
400 }
401}
402
403impl Hash for VariantType {
404 #[inline]
405 fn hash<H: Hasher>(&self, state: &mut H) {
406 <VariantTy as Hash>::hash(self, state)
407 }
408}
409
410impl<'a> From<VariantType> for Cow<'a, VariantTy> {
411 #[inline]
412 fn from(ty: VariantType) -> Cow<'a, VariantTy> {
413 Cow::Owned(ty)
414 }
415}
416
417#[doc(hidden)]
418impl IntoGlibPtr<*mut ffi::GVariantType> for VariantType {
419 #[inline]
420 fn into_glib_ptr(self) -> *mut ffi::GVariantType {
421 std::mem::ManuallyDrop::new(self).to_glib_none().0
422 }
423}
424
425#[doc(hidden)]
426impl<'a> ToGlibPtr<'a, *const ffi::GVariantType> for VariantType {
427 type Storage = PhantomData<&'a Self>;
428
429 #[inline]
430 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GVariantType, Self> {
431 Stash(self.ptr.as_ptr(), PhantomData)
432 }
433
434 #[inline]
435 fn to_glib_full(&self) -> *const ffi::GVariantType {
436 unsafe { ffi::g_variant_type_copy(self.ptr.as_ptr()) }
437 }
438}
439
440#[doc(hidden)]
441impl<'a> ToGlibPtr<'a, *mut ffi::GVariantType> for VariantType {
442 type Storage = PhantomData<&'a Self>;
443
444 #[inline]
445 fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GVariantType, Self> {
446 Stash(self.ptr.as_ptr(), PhantomData)
447 }
448
449 #[inline]
450 fn to_glib_full(&self) -> *mut ffi::GVariantType {
451 unsafe { ffi::g_variant_type_copy(self.ptr.as_ptr()) }
452 }
453}
454
455#[doc(hidden)]
456impl<'a> ToGlibPtrMut<'a, *mut ffi::GVariantType> for VariantType {
457 type Storage = PhantomData<&'a mut Self>;
458
459 #[inline]
460 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GVariantType, Self> {
461 StashMut(self.ptr.as_ptr(), PhantomData)
462 }
463}
464
465#[doc(hidden)]
466impl FromGlibPtrNone<*const ffi::GVariantType> for VariantType {
467 #[inline]
468 unsafe fn from_glib_none(ptr: *const ffi::GVariantType) -> VariantType {
469 unsafe { VariantTy::from_ptr(ptr).to_owned() }
470 }
471}
472
473#[doc(hidden)]
474impl FromGlibPtrFull<*const ffi::GVariantType> for VariantType {
475 #[inline]
476 unsafe fn from_glib_full(ptr: *const ffi::GVariantType) -> VariantType {
477 unsafe {
478 VariantTy::from_ptr(ptr).to_owned()
481 }
482 }
483}
484
485#[doc(hidden)]
486impl FromGlibPtrFull<*mut ffi::GVariantType> for VariantType {
487 #[inline]
488 unsafe fn from_glib_full(ptr: *mut ffi::GVariantType) -> VariantType {
489 unsafe {
490 debug_assert!(!ptr.is_null());
491 let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
492 VariantType {
493 ptr: ptr::NonNull::new_unchecked(ptr),
494 len,
495 }
496 }
497 }
498}
499
500#[repr(transparent)]
506#[derive(Debug, PartialEq, Eq, Hash)]
507pub struct VariantTy {
508 inner: str,
509}
510
511impl VariantTy {
512 #[doc(alias = "G_VARIANT_TYPE_BOOLEAN")]
515 pub const BOOLEAN: &'static VariantTy =
516 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BOOLEAN) };
517
518 #[doc(alias = "G_VARIANT_TYPE_BYTE")]
521 pub const BYTE: &'static VariantTy =
522 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE) };
523
524 #[doc(alias = "G_VARIANT_TYPE_INT16")]
527 pub const INT16: &'static VariantTy =
528 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT16) };
529
530 #[doc(alias = "G_VARIANT_TYPE_UINT16")]
533 pub const UINT16: &'static VariantTy =
534 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT16) };
535
536 #[doc(alias = "G_VARIANT_TYPE_INT32")]
539 pub const INT32: &'static VariantTy =
540 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT32) };
541
542 #[doc(alias = "G_VARIANT_TYPE_UINT32")]
545 pub const UINT32: &'static VariantTy =
546 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT32) };
547
548 #[doc(alias = "G_VARIANT_TYPE_INT64")]
551 pub const INT64: &'static VariantTy =
552 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT64) };
553
554 #[doc(alias = "G_VARIANT_TYPE_UINT64")]
557 pub const UINT64: &'static VariantTy =
558 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT64) };
559
560 #[doc(alias = "G_VARIANT_TYPE_DOUBLE")]
563 pub const DOUBLE: &'static VariantTy =
564 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DOUBLE) };
565
566 #[doc(alias = "G_VARIANT_TYPE_STRING")]
569 pub const STRING: &'static VariantTy =
570 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING) };
571
572 #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH")]
575 pub const OBJECT_PATH: &'static VariantTy =
576 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH) };
577
578 #[doc(alias = "G_VARIANT_TYPE_SIGNATURE")]
581 pub const SIGNATURE: &'static VariantTy =
582 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_SIGNATURE) };
583
584 #[doc(alias = "G_VARIANT_TYPE_VARIANT")]
587 pub const VARIANT: &'static VariantTy =
588 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARIANT) };
589
590 #[doc(alias = "G_VARIANT_TYPE_HANDLE")]
593 pub const HANDLE: &'static VariantTy =
594 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_HANDLE) };
595
596 #[doc(alias = "G_VARIANT_TYPE_UNIT")]
599 pub const UNIT: &'static VariantTy =
600 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UNIT) };
601
602 #[doc(alias = "G_VARIANT_TYPE_ANY")]
605 pub const ANY: &'static VariantTy =
606 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ANY) };
607
608 #[doc(alias = "G_VARIANT_TYPE_BASIC")]
611 pub const BASIC: &'static VariantTy =
612 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BASIC) };
613
614 #[doc(alias = "G_VARIANT_TYPE_MAYBE")]
617 pub const MAYBE: &'static VariantTy =
618 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_MAYBE) };
619
620 #[doc(alias = "G_VARIANT_TYPE_ARRAY")]
623 pub const ARRAY: &'static VariantTy =
624 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ARRAY) };
625
626 #[doc(alias = "G_VARIANT_TYPE_TUPLE")]
629 pub const TUPLE: &'static VariantTy =
630 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_TUPLE) };
631
632 #[doc(alias = "G_VARIANT_TYPE_DICT_ENTRY")]
635 pub const DICT_ENTRY: &'static VariantTy =
636 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICT_ENTRY) };
637
638 #[doc(alias = "G_VARIANT_TYPE_DICTIONARY")]
641 pub const DICTIONARY: &'static VariantTy =
642 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICTIONARY) };
643
644 #[doc(alias = "G_VARIANT_TYPE_STRING_ARRAY")]
647 pub const STRING_ARRAY: &'static VariantTy =
648 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING_ARRAY) };
649
650 #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH_ARRAY")]
653 pub const OBJECT_PATH_ARRAY: &'static VariantTy =
654 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH_ARRAY) };
655
656 #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING")]
659 pub const BYTE_STRING: &'static VariantTy =
660 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING) };
661
662 #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING_ARRAY")]
665 pub const BYTE_STRING_ARRAY: &'static VariantTy =
666 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING_ARRAY) };
667
668 #[doc(alias = "G_VARIANT_TYPE_VARDICT")]
671 pub const VARDICT: &'static VariantTy =
672 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARDICT) };
673
674 pub fn new(type_string: &str) -> Result<&VariantTy, BoolError> {
679 unsafe {
680 let ptr = type_string.as_ptr();
681 let limit = ptr.add(type_string.len());
682 let mut end = ptr::null();
683
684 let ok = from_glib(ffi::g_variant_type_string_scan(
685 ptr as *const _,
686 limit as *const _,
687 &mut end,
688 ));
689 if ok && end as *const _ == limit {
690 Ok(&*(type_string.as_bytes() as *const [u8] as *const VariantTy))
691 } else {
692 Err(bool_error!("Invalid type string: '{}'", type_string))
693 }
694 }
695 }
696
697 #[inline]
704 pub const unsafe fn from_str_unchecked(type_string: &str) -> &VariantTy {
705 unsafe { std::mem::transmute::<&str, &VariantTy>(type_string) }
706 }
707
708 #[doc(hidden)]
712 #[allow(clippy::cast_slice_from_raw_parts)]
713 #[inline]
714 pub unsafe fn from_ptr<'a>(ptr: *const ffi::GVariantType) -> &'a VariantTy {
715 unsafe {
716 debug_assert!(!ptr.is_null());
717 let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
718 debug_assert!(len > 0);
719 &*(slice::from_raw_parts(ptr as *const u8, len) as *const [u8] as *const VariantTy)
720 }
721 }
722
723 #[doc(hidden)]
726 #[inline]
727 pub fn as_ptr(&self) -> *const ffi::GVariantType {
728 self.inner.as_ptr() as *const _
729 }
730
731 #[inline]
734 pub fn as_str(&self) -> &str {
735 &self.inner
736 }
737
738 #[doc(alias = "g_variant_type_is_definite")]
741 pub fn is_definite(&self) -> bool {
742 unsafe { from_glib(ffi::g_variant_type_is_definite(self.to_glib_none().0)) }
743 }
744
745 #[doc(alias = "g_variant_type_is_container")]
748 pub fn is_container(&self) -> bool {
749 unsafe { from_glib(ffi::g_variant_type_is_container(self.to_glib_none().0)) }
750 }
751
752 #[doc(alias = "g_variant_type_is_basic")]
755 pub fn is_basic(&self) -> bool {
756 unsafe { from_glib(ffi::g_variant_type_is_basic(self.to_glib_none().0)) }
757 }
758
759 #[doc(alias = "g_variant_type_is_maybe")]
762 pub fn is_maybe(&self) -> bool {
763 unsafe { from_glib(ffi::g_variant_type_is_maybe(self.to_glib_none().0)) }
764 }
765
766 #[doc(alias = "g_variant_type_is_array")]
769 pub fn is_array(&self) -> bool {
770 unsafe { from_glib(ffi::g_variant_type_is_array(self.to_glib_none().0)) }
771 }
772
773 #[doc(alias = "g_variant_type_is_tuple")]
776 pub fn is_tuple(&self) -> bool {
777 unsafe { from_glib(ffi::g_variant_type_is_tuple(self.to_glib_none().0)) }
778 }
779
780 #[doc(alias = "g_variant_type_is_dict_entry")]
783 pub fn is_dict_entry(&self) -> bool {
784 unsafe { from_glib(ffi::g_variant_type_is_dict_entry(self.to_glib_none().0)) }
785 }
786
787 #[doc(alias = "g_variant_type_is_variant")]
790 pub fn is_variant(&self) -> bool {
791 unsafe { from_glib(ffi::g_variant_type_is_variant(self.to_glib_none().0)) }
792 }
793
794 #[doc(alias = "g_variant_type_is_subtype_of")]
797 pub fn is_subtype_of(&self, supertype: &Self) -> bool {
798 unsafe {
799 from_glib(ffi::g_variant_type_is_subtype_of(
800 self.to_glib_none().0,
801 supertype.to_glib_none().0,
802 ))
803 }
804 }
805
806 #[doc(alias = "g_variant_type_element")]
813 pub fn element(&self) -> &VariantTy {
814 assert!(self.is_array() || self.is_maybe());
815
816 unsafe {
817 let element = ffi::g_variant_type_element(self.to_glib_none().0);
818 Self::from_ptr(element)
819 }
820 }
821
822 pub fn tuple_types(&self) -> VariantTyIterator<'_> {
829 VariantTyIterator::new(self).expect("VariantTy does not represent a tuple")
830 }
831
832 #[doc(alias = "g_variant_type_first")]
839 pub fn first(&self) -> Option<&VariantTy> {
840 assert!(self.as_str().starts_with('(') || self.as_str().starts_with('{'));
841
842 unsafe {
843 let first = ffi::g_variant_type_first(self.to_glib_none().0);
844 if first.is_null() {
845 None
846 } else {
847 Some(Self::from_ptr(first))
848 }
849 }
850 }
851
852 #[doc(alias = "g_variant_type_next")]
855 pub fn next(&self) -> Option<&VariantTy> {
856 unsafe {
857 let next = ffi::g_variant_type_next(self.to_glib_none().0);
858 if next.is_null() {
859 None
860 } else {
861 Some(Self::from_ptr(next))
862 }
863 }
864 }
865
866 #[doc(alias = "g_variant_type_n_items")]
869 pub fn n_items(&self) -> usize {
870 unsafe { ffi::g_variant_type_n_items(self.to_glib_none().0) }
871 }
872
873 #[doc(alias = "g_variant_type_key")]
880 pub fn key(&self) -> &VariantTy {
881 assert!(self.as_str().starts_with('{'));
882
883 unsafe {
884 let key = ffi::g_variant_type_key(self.to_glib_none().0);
885 Self::from_ptr(key)
886 }
887 }
888
889 #[doc(alias = "g_variant_type_value")]
896 pub fn value(&self) -> &VariantTy {
897 assert!(self.as_str().starts_with('{'));
898
899 unsafe {
900 let value = ffi::g_variant_type_value(self.to_glib_none().0);
901 Self::from_ptr(value)
902 }
903 }
904
905 pub(crate) fn as_array<'a>(&self) -> Cow<'a, VariantTy> {
908 if self == VariantTy::STRING {
909 Cow::Borrowed(VariantTy::STRING_ARRAY)
910 } else if self == VariantTy::BYTE {
911 Cow::Borrowed(VariantTy::BYTE_STRING)
912 } else if self == VariantTy::BYTE_STRING {
913 Cow::Borrowed(VariantTy::BYTE_STRING_ARRAY)
914 } else if self == VariantTy::OBJECT_PATH {
915 Cow::Borrowed(VariantTy::OBJECT_PATH_ARRAY)
916 } else if self == VariantTy::DICT_ENTRY {
917 Cow::Borrowed(VariantTy::DICTIONARY)
918 } else {
919 Cow::Owned(VariantType::new_array(self))
920 }
921 }
922}
923
924unsafe impl Sync for VariantTy {}
925
926#[doc(hidden)]
927impl<'a> ToGlibPtr<'a, *const ffi::GVariantType> for VariantTy {
928 type Storage = PhantomData<&'a Self>;
929
930 #[inline]
931 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GVariantType, Self> {
932 Stash(self.as_ptr(), PhantomData)
933 }
934}
935
936impl fmt::Display for VariantTy {
937 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
938 f.write_str(self.as_str())
939 }
940}
941
942impl<'a> From<&'a VariantTy> for Cow<'a, VariantTy> {
943 #[inline]
944 fn from(ty: &'a VariantTy) -> Cow<'a, VariantTy> {
945 Cow::Borrowed(ty)
946 }
947}
948
949impl AsRef<VariantTy> for VariantTy {
950 #[inline]
951 fn as_ref(&self) -> &Self {
952 self
953 }
954}
955
956impl ToOwned for VariantTy {
957 type Owned = VariantType;
958
959 #[inline]
960 fn to_owned(&self) -> VariantType {
961 unsafe {
962 VariantType {
963 ptr: ptr::NonNull::new_unchecked(ffi::g_variant_type_copy(self.as_ptr())),
964 len: self.inner.len(),
965 }
966 }
967 }
968}
969
970impl StaticType for VariantTy {
971 #[inline]
972 fn static_type() -> Type {
973 unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
974 }
975}
976
977#[doc(hidden)]
978unsafe impl<'a> crate::value::FromValue<'a> for &'a VariantTy {
979 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
980
981 unsafe fn from_value(value: &'a crate::Value) -> Self {
982 unsafe {
983 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
984 debug_assert!(!ptr.is_null());
985 VariantTy::from_ptr(ptr as *const ffi::GVariantType)
986 }
987 }
988}
989
990#[doc(hidden)]
991impl crate::value::ToValue for VariantTy {
992 fn to_value(&self) -> crate::Value {
993 unsafe {
994 let mut value = crate::Value::from_type_unchecked(VariantTy::static_type());
995 gobject_ffi::g_value_set_boxed(
996 value.to_glib_none_mut().0,
997 self.to_glib_none().0 as *mut _,
998 );
999 value
1000 }
1001 }
1002
1003 fn value_type(&self) -> crate::Type {
1004 VariantTy::static_type()
1005 }
1006}
1007
1008#[doc(hidden)]
1009impl crate::value::ToValue for &VariantTy {
1010 fn to_value(&self) -> crate::Value {
1011 (*self).to_value()
1012 }
1013
1014 #[inline]
1015 fn value_type(&self) -> crate::Type {
1016 VariantTy::static_type()
1017 }
1018}
1019
1020#[doc(hidden)]
1021impl crate::value::ToValueOptional for &VariantTy {
1022 fn to_value_optional(s: Option<&Self>) -> crate::Value {
1023 let mut value = crate::Value::for_value_type::<VariantType>();
1024 unsafe {
1025 gobject_ffi::g_value_set_boxed(
1026 value.to_glib_none_mut().0,
1027 s.to_glib_none().0 as *mut _,
1028 );
1029 }
1030
1031 value
1032 }
1033}
1034
1035impl StaticType for VariantType {
1036 #[inline]
1037 fn static_type() -> Type {
1038 unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
1039 }
1040}
1041
1042#[doc(hidden)]
1043impl crate::value::ValueType for VariantType {
1044 type Type = VariantType;
1045}
1046
1047#[doc(hidden)]
1048impl crate::value::ValueTypeOptional for VariantType {}
1049
1050#[doc(hidden)]
1051unsafe impl<'a> crate::value::FromValue<'a> for VariantType {
1052 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
1053
1054 unsafe fn from_value(value: &'a crate::Value) -> Self {
1055 unsafe {
1056 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
1057 debug_assert!(!ptr.is_null());
1058 from_glib_none(ptr as *const ffi::GVariantType)
1059 }
1060 }
1061}
1062
1063#[doc(hidden)]
1064impl crate::value::ToValue for VariantType {
1065 fn to_value(&self) -> crate::Value {
1066 unsafe {
1067 let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
1068 gobject_ffi::g_value_set_boxed(
1069 value.to_glib_none_mut().0,
1070 ToGlibPtr::<*mut _>::to_glib_none(&self).0 as *mut _,
1071 );
1072 value
1073 }
1074 }
1075
1076 fn value_type(&self) -> crate::Type {
1077 VariantType::static_type()
1078 }
1079}
1080
1081#[doc(hidden)]
1082impl From<VariantType> for crate::Value {
1083 fn from(t: VariantType) -> Self {
1084 unsafe {
1085 let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
1086 gobject_ffi::g_value_take_boxed(
1087 value.to_glib_none_mut().0,
1088 IntoGlibPtr::<*mut _>::into_glib_ptr(t) as *mut _,
1089 );
1090 value
1091 }
1092 }
1093}
1094
1095#[doc(hidden)]
1096impl crate::value::ToValueOptional for VariantType {
1097 fn to_value_optional(s: Option<&Self>) -> crate::Value {
1098 let mut value = crate::Value::for_value_type::<Self>();
1099 unsafe {
1100 gobject_ffi::g_value_set_boxed(
1101 value.to_glib_none_mut().0,
1102 ToGlibPtr::<*mut _>::to_glib_none(&s).0 as *mut _,
1103 );
1104 }
1105
1106 value
1107 }
1108}
1109
1110impl PartialEq for VariantType {
1111 #[inline]
1112 fn eq(&self, other: &Self) -> bool {
1113 <VariantTy as PartialEq>::eq(self, other)
1114 }
1115}
1116
1117macro_rules! impl_eq {
1118 ($lhs:ty, $rhs: ty) => {
1119 #[allow(clippy::extra_unused_lifetimes)]
1120 impl<'a, 'b> PartialEq<$rhs> for $lhs {
1121 #[inline]
1122 fn eq(&self, other: &$rhs) -> bool {
1123 <VariantTy as PartialEq>::eq(self, other)
1124 }
1125 }
1126
1127 #[allow(clippy::extra_unused_lifetimes)]
1128 impl<'a, 'b> PartialEq<$lhs> for $rhs {
1129 #[inline]
1130 fn eq(&self, other: &$lhs) -> bool {
1131 <VariantTy as PartialEq>::eq(self, other)
1132 }
1133 }
1134 };
1135}
1136
1137impl_eq!(VariantType, VariantTy);
1138impl_eq!(VariantType, &'a VariantTy);
1139impl_eq!(VariantType, Cow<'a, VariantTy>);
1140impl_eq!(&'a VariantTy, Cow<'b, VariantTy>);
1141
1142macro_rules! impl_str_eq {
1143 ($lhs:ty, $rhs: ty) => {
1144 #[allow(clippy::redundant_slicing)]
1145 #[allow(clippy::extra_unused_lifetimes)]
1146 impl<'a, 'b> PartialEq<$rhs> for $lhs {
1147 #[inline]
1148 fn eq(&self, other: &$rhs) -> bool {
1149 self.as_str().eq(&other[..])
1150 }
1151 }
1152
1153 #[allow(clippy::extra_unused_lifetimes)]
1154 impl<'a, 'b> PartialEq<$lhs> for $rhs {
1155 #[inline]
1156 fn eq(&self, other: &$lhs) -> bool {
1157 self[..].eq(other.as_str())
1158 }
1159 }
1160 };
1161}
1162
1163impl_str_eq!(VariantTy, str);
1164impl_str_eq!(VariantTy, &'a str);
1165impl_str_eq!(&'a VariantTy, str);
1166impl_str_eq!(VariantTy, String);
1167impl_str_eq!(&'a VariantTy, String);
1168impl_str_eq!(VariantType, str);
1169impl_str_eq!(VariantType, &'a str);
1170impl_str_eq!(VariantType, String);
1171
1172impl Eq for VariantType {}
1173
1174#[derive(Debug, Copy, Clone)]
1179pub struct VariantTyIterator<'a> {
1180 elem: Option<&'a VariantTy>,
1181}
1182
1183impl<'a> VariantTyIterator<'a> {
1184 pub fn new(ty: &'a VariantTy) -> Result<Self, BoolError> {
1190 if (ty.is_tuple() && ty != VariantTy::TUPLE) || ty.is_dict_entry() {
1191 Ok(Self { elem: ty.first() })
1192 } else {
1193 Err(bool_error!(
1194 "Expected a definite tuple or dictionary entry type"
1195 ))
1196 }
1197 }
1198}
1199
1200impl<'a> Iterator for VariantTyIterator<'a> {
1201 type Item = &'a VariantTy;
1202
1203 #[doc(alias = "g_variant_type_next")]
1204 fn next(&mut self) -> Option<Self::Item> {
1205 let elem = self.elem?;
1206 self.elem = elem.next();
1207 Some(elem)
1208 }
1209}
1210
1211impl iter::FusedIterator for VariantTyIterator<'_> {}
1212
1213#[cfg(test)]
1214mod tests {
1215 use super::*;
1216
1217 unsafe fn equal<T, U>(ptr1: *const T, ptr2: *const U) -> bool {
1218 unsafe {
1219 from_glib(ffi::g_variant_type_equal(
1220 ptr1 as *const _,
1221 ptr2 as *const _,
1222 ))
1223 }
1224 }
1225
1226 #[test]
1227 fn new() {
1228 let ty = VariantTy::new("((iii)s)").unwrap();
1229 unsafe {
1230 assert!(equal(ty.as_ptr(), b"((iii)s)\0" as *const u8));
1231 }
1232 }
1233
1234 #[test]
1235 fn new_empty() {
1236 assert!(VariantTy::new("").is_err());
1237 }
1238
1239 #[test]
1240 fn new_with_nul() {
1241 assert!(VariantTy::new("((iii\0)s)").is_err());
1242 }
1243
1244 #[test]
1245 fn new_too_short() {
1246 assert!(VariantTy::new("((iii").is_err());
1247 }
1248
1249 #[test]
1250 fn new_too_long() {
1251 assert!(VariantTy::new("(iii)s").is_err());
1252 }
1253
1254 #[test]
1255 fn eq() {
1256 let ty1 = VariantTy::new("((iii)s)").unwrap();
1257 let ty2 = VariantTy::new("((iii)s)").unwrap();
1258 assert_eq!(ty1, ty2);
1259 assert_eq!(ty1, "((iii)s)");
1260 unsafe {
1261 assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
1262 }
1263 }
1264
1265 #[test]
1266 fn ne() {
1267 let ty1 = VariantTy::new("((iii)s)").unwrap();
1268 let ty2 = VariantTy::new("((iii)o)").unwrap();
1269 assert_ne!(ty1, ty2);
1270 assert_ne!(ty1, "((iii)o)");
1271 unsafe {
1272 assert!(!equal(ty1.as_ptr(), ty2.as_ptr()));
1273 }
1274 }
1275
1276 #[test]
1277 fn from_bytes() {
1278 unsafe {
1279 let ty = VariantTy::from_ptr(b"((iii)s)" as *const u8 as *const _);
1280 assert_eq!(ty, "((iii)s)");
1281 assert!(equal(ty.as_ptr(), "((iii)s)".as_ptr()));
1282 }
1283 }
1284
1285 #[test]
1286 fn to_owned() {
1287 let ty1 = VariantTy::new("((iii)s)").unwrap();
1288 let ty2 = ty1.to_owned();
1289 assert_eq!(ty1, ty2);
1290 assert_eq!(ty2, "((iii)s)");
1291 unsafe {
1292 assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
1293 }
1294 }
1295
1296 #[test]
1297 fn value() {
1298 let ty1 = VariantType::new("*").unwrap();
1299 let tyv = ty1.to_value();
1300 let ty2 = tyv.get::<VariantType>().unwrap();
1301 assert_eq!(ty1, ty2);
1302
1303 let ty3 = VariantTy::new("*").unwrap();
1304 let tyv2 = ty3.to_value();
1305 let ty4 = tyv2.get::<VariantType>().unwrap();
1306 assert_eq!(ty3, ty4);
1307
1308 let ty5 = VariantTy::ANY;
1309 let tyv3 = ty5.to_value();
1310 let ty6 = tyv3.get::<VariantType>().unwrap();
1311 assert_eq!(ty5, ty6);
1312 }
1313
1314 #[test]
1315 fn type_() {
1316 assert_eq!(VariantTy::static_type(), VariantType::static_type())
1317 }
1318
1319 #[test]
1320 fn tuple_iter() {
1321 let ty = VariantTy::new("((iii)s)").unwrap();
1322 let types: Vec<_> = ty.tuple_types().map(|t| t.as_str()).collect();
1323 assert_eq!(&types, &["(iii)", "s"]);
1324 }
1325}