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::{ffi, gobject_ffi, prelude::*, translate::*, BoolError, Type};
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 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 VariantTy::from_ptr(ptr).to_owned()
480 }
481}
482
483#[doc(hidden)]
484impl FromGlibPtrFull<*mut ffi::GVariantType> for VariantType {
485 #[inline]
486 unsafe fn from_glib_full(ptr: *mut ffi::GVariantType) -> VariantType {
487 debug_assert!(!ptr.is_null());
488 let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
489 VariantType {
490 ptr: ptr::NonNull::new_unchecked(ptr),
491 len,
492 }
493 }
494}
495
496#[repr(transparent)]
502#[derive(Debug, PartialEq, Eq, Hash)]
503pub struct VariantTy {
504 inner: str,
505}
506
507impl VariantTy {
508 #[doc(alias = "G_VARIANT_TYPE_BOOLEAN")]
511 pub const BOOLEAN: &'static VariantTy =
512 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BOOLEAN) };
513
514 #[doc(alias = "G_VARIANT_TYPE_BYTE")]
517 pub const BYTE: &'static VariantTy =
518 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE) };
519
520 #[doc(alias = "G_VARIANT_TYPE_INT16")]
523 pub const INT16: &'static VariantTy =
524 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT16) };
525
526 #[doc(alias = "G_VARIANT_TYPE_UINT16")]
529 pub const UINT16: &'static VariantTy =
530 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT16) };
531
532 #[doc(alias = "G_VARIANT_TYPE_INT32")]
535 pub const INT32: &'static VariantTy =
536 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT32) };
537
538 #[doc(alias = "G_VARIANT_TYPE_UINT32")]
541 pub const UINT32: &'static VariantTy =
542 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT32) };
543
544 #[doc(alias = "G_VARIANT_TYPE_INT64")]
547 pub const INT64: &'static VariantTy =
548 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT64) };
549
550 #[doc(alias = "G_VARIANT_TYPE_UINT64")]
553 pub const UINT64: &'static VariantTy =
554 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT64) };
555
556 #[doc(alias = "G_VARIANT_TYPE_DOUBLE")]
559 pub const DOUBLE: &'static VariantTy =
560 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DOUBLE) };
561
562 #[doc(alias = "G_VARIANT_TYPE_STRING")]
565 pub const STRING: &'static VariantTy =
566 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING) };
567
568 #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH")]
571 pub const OBJECT_PATH: &'static VariantTy =
572 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH) };
573
574 #[doc(alias = "G_VARIANT_TYPE_SIGNATURE")]
577 pub const SIGNATURE: &'static VariantTy =
578 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_SIGNATURE) };
579
580 #[doc(alias = "G_VARIANT_TYPE_VARIANT")]
583 pub const VARIANT: &'static VariantTy =
584 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARIANT) };
585
586 #[doc(alias = "G_VARIANT_TYPE_HANDLE")]
589 pub const HANDLE: &'static VariantTy =
590 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_HANDLE) };
591
592 #[doc(alias = "G_VARIANT_TYPE_UNIT")]
595 pub const UNIT: &'static VariantTy =
596 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UNIT) };
597
598 #[doc(alias = "G_VARIANT_TYPE_ANY")]
601 pub const ANY: &'static VariantTy =
602 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ANY) };
603
604 #[doc(alias = "G_VARIANT_TYPE_BASIC")]
607 pub const BASIC: &'static VariantTy =
608 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BASIC) };
609
610 #[doc(alias = "G_VARIANT_TYPE_MAYBE")]
613 pub const MAYBE: &'static VariantTy =
614 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_MAYBE) };
615
616 #[doc(alias = "G_VARIANT_TYPE_ARRAY")]
619 pub const ARRAY: &'static VariantTy =
620 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ARRAY) };
621
622 #[doc(alias = "G_VARIANT_TYPE_TUPLE")]
625 pub const TUPLE: &'static VariantTy =
626 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_TUPLE) };
627
628 #[doc(alias = "G_VARIANT_TYPE_DICT_ENTRY")]
631 pub const DICT_ENTRY: &'static VariantTy =
632 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICT_ENTRY) };
633
634 #[doc(alias = "G_VARIANT_TYPE_DICTIONARY")]
637 pub const DICTIONARY: &'static VariantTy =
638 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICTIONARY) };
639
640 #[doc(alias = "G_VARIANT_TYPE_STRING_ARRAY")]
643 pub const STRING_ARRAY: &'static VariantTy =
644 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING_ARRAY) };
645
646 #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH_ARRAY")]
649 pub const OBJECT_PATH_ARRAY: &'static VariantTy =
650 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH_ARRAY) };
651
652 #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING")]
655 pub const BYTE_STRING: &'static VariantTy =
656 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING) };
657
658 #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING_ARRAY")]
661 pub const BYTE_STRING_ARRAY: &'static VariantTy =
662 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING_ARRAY) };
663
664 #[doc(alias = "G_VARIANT_TYPE_VARDICT")]
667 pub const VARDICT: &'static VariantTy =
668 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARDICT) };
669
670 pub fn new(type_string: &str) -> Result<&VariantTy, BoolError> {
675 unsafe {
676 let ptr = type_string.as_ptr();
677 let limit = ptr.add(type_string.len());
678 let mut end = ptr::null();
679
680 let ok = from_glib(ffi::g_variant_type_string_scan(
681 ptr as *const _,
682 limit as *const _,
683 &mut end,
684 ));
685 if ok && end as *const _ == limit {
686 Ok(&*(type_string.as_bytes() as *const [u8] as *const VariantTy))
687 } else {
688 Err(bool_error!("Invalid type string: '{}'", type_string))
689 }
690 }
691 }
692
693 #[inline]
700 pub const unsafe fn from_str_unchecked(type_string: &str) -> &VariantTy {
701 std::mem::transmute::<&str, &VariantTy>(type_string)
702 }
703
704 #[doc(hidden)]
708 #[allow(clippy::cast_slice_from_raw_parts)]
709 #[inline]
710 pub unsafe fn from_ptr<'a>(ptr: *const ffi::GVariantType) -> &'a VariantTy {
711 debug_assert!(!ptr.is_null());
712 let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
713 debug_assert!(len > 0);
714 &*(slice::from_raw_parts(ptr as *const u8, len) as *const [u8] as *const VariantTy)
715 }
716
717 #[doc(hidden)]
720 #[inline]
721 pub fn as_ptr(&self) -> *const ffi::GVariantType {
722 self.inner.as_ptr() as *const _
723 }
724
725 #[inline]
728 pub fn as_str(&self) -> &str {
729 &self.inner
730 }
731
732 #[doc(alias = "g_variant_type_is_definite")]
735 pub fn is_definite(&self) -> bool {
736 unsafe { from_glib(ffi::g_variant_type_is_definite(self.to_glib_none().0)) }
737 }
738
739 #[doc(alias = "g_variant_type_is_container")]
742 pub fn is_container(&self) -> bool {
743 unsafe { from_glib(ffi::g_variant_type_is_container(self.to_glib_none().0)) }
744 }
745
746 #[doc(alias = "g_variant_type_is_basic")]
749 pub fn is_basic(&self) -> bool {
750 unsafe { from_glib(ffi::g_variant_type_is_basic(self.to_glib_none().0)) }
751 }
752
753 #[doc(alias = "g_variant_type_is_maybe")]
756 pub fn is_maybe(&self) -> bool {
757 unsafe { from_glib(ffi::g_variant_type_is_maybe(self.to_glib_none().0)) }
758 }
759
760 #[doc(alias = "g_variant_type_is_array")]
763 pub fn is_array(&self) -> bool {
764 unsafe { from_glib(ffi::g_variant_type_is_array(self.to_glib_none().0)) }
765 }
766
767 #[doc(alias = "g_variant_type_is_tuple")]
770 pub fn is_tuple(&self) -> bool {
771 unsafe { from_glib(ffi::g_variant_type_is_tuple(self.to_glib_none().0)) }
772 }
773
774 #[doc(alias = "g_variant_type_is_dict_entry")]
777 pub fn is_dict_entry(&self) -> bool {
778 unsafe { from_glib(ffi::g_variant_type_is_dict_entry(self.to_glib_none().0)) }
779 }
780
781 #[doc(alias = "g_variant_type_is_variant")]
784 pub fn is_variant(&self) -> bool {
785 unsafe { from_glib(ffi::g_variant_type_is_variant(self.to_glib_none().0)) }
786 }
787
788 #[doc(alias = "g_variant_type_is_subtype_of")]
791 pub fn is_subtype_of(&self, supertype: &Self) -> bool {
792 unsafe {
793 from_glib(ffi::g_variant_type_is_subtype_of(
794 self.to_glib_none().0,
795 supertype.to_glib_none().0,
796 ))
797 }
798 }
799
800 #[doc(alias = "g_variant_type_element")]
807 pub fn element(&self) -> &VariantTy {
808 assert!(self.is_array() || self.is_maybe());
809
810 unsafe {
811 let element = ffi::g_variant_type_element(self.to_glib_none().0);
812 Self::from_ptr(element)
813 }
814 }
815
816 pub fn tuple_types(&self) -> VariantTyIterator<'_> {
823 VariantTyIterator::new(self).expect("VariantTy does not represent a tuple")
824 }
825
826 #[doc(alias = "g_variant_type_first")]
833 pub fn first(&self) -> Option<&VariantTy> {
834 assert!(self.as_str().starts_with('(') || self.as_str().starts_with('{'));
835
836 unsafe {
837 let first = ffi::g_variant_type_first(self.to_glib_none().0);
838 if first.is_null() {
839 None
840 } else {
841 Some(Self::from_ptr(first))
842 }
843 }
844 }
845
846 #[doc(alias = "g_variant_type_next")]
849 pub fn next(&self) -> Option<&VariantTy> {
850 unsafe {
851 let next = ffi::g_variant_type_next(self.to_glib_none().0);
852 if next.is_null() {
853 None
854 } else {
855 Some(Self::from_ptr(next))
856 }
857 }
858 }
859
860 #[doc(alias = "g_variant_type_n_items")]
863 pub fn n_items(&self) -> usize {
864 unsafe { ffi::g_variant_type_n_items(self.to_glib_none().0) }
865 }
866
867 #[doc(alias = "g_variant_type_key")]
874 pub fn key(&self) -> &VariantTy {
875 assert!(self.as_str().starts_with('{'));
876
877 unsafe {
878 let key = ffi::g_variant_type_key(self.to_glib_none().0);
879 Self::from_ptr(key)
880 }
881 }
882
883 #[doc(alias = "g_variant_type_value")]
890 pub fn value(&self) -> &VariantTy {
891 assert!(self.as_str().starts_with('{'));
892
893 unsafe {
894 let value = ffi::g_variant_type_value(self.to_glib_none().0);
895 Self::from_ptr(value)
896 }
897 }
898
899 pub(crate) fn as_array<'a>(&self) -> Cow<'a, VariantTy> {
902 if self == VariantTy::STRING {
903 Cow::Borrowed(VariantTy::STRING_ARRAY)
904 } else if self == VariantTy::BYTE {
905 Cow::Borrowed(VariantTy::BYTE_STRING)
906 } else if self == VariantTy::BYTE_STRING {
907 Cow::Borrowed(VariantTy::BYTE_STRING_ARRAY)
908 } else if self == VariantTy::OBJECT_PATH {
909 Cow::Borrowed(VariantTy::OBJECT_PATH_ARRAY)
910 } else if self == VariantTy::DICT_ENTRY {
911 Cow::Borrowed(VariantTy::DICTIONARY)
912 } else {
913 Cow::Owned(VariantType::new_array(self))
914 }
915 }
916}
917
918unsafe impl Sync for VariantTy {}
919
920#[doc(hidden)]
921impl<'a> ToGlibPtr<'a, *const ffi::GVariantType> for VariantTy {
922 type Storage = PhantomData<&'a Self>;
923
924 #[inline]
925 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GVariantType, Self> {
926 Stash(self.as_ptr(), PhantomData)
927 }
928}
929
930impl fmt::Display for VariantTy {
931 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
932 f.write_str(self.as_str())
933 }
934}
935
936impl<'a> From<&'a VariantTy> for Cow<'a, VariantTy> {
937 #[inline]
938 fn from(ty: &'a VariantTy) -> Cow<'a, VariantTy> {
939 Cow::Borrowed(ty)
940 }
941}
942
943impl AsRef<VariantTy> for VariantTy {
944 #[inline]
945 fn as_ref(&self) -> &Self {
946 self
947 }
948}
949
950impl ToOwned for VariantTy {
951 type Owned = VariantType;
952
953 #[inline]
954 fn to_owned(&self) -> VariantType {
955 unsafe {
956 VariantType {
957 ptr: ptr::NonNull::new_unchecked(ffi::g_variant_type_copy(self.as_ptr())),
958 len: self.inner.len(),
959 }
960 }
961 }
962}
963
964impl StaticType for VariantTy {
965 #[inline]
966 fn static_type() -> Type {
967 unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
968 }
969}
970
971#[doc(hidden)]
972unsafe impl<'a> crate::value::FromValue<'a> for &'a VariantTy {
973 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
974
975 unsafe fn from_value(value: &'a crate::Value) -> Self {
976 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
977 debug_assert!(!ptr.is_null());
978 VariantTy::from_ptr(ptr as *const ffi::GVariantType)
979 }
980}
981
982#[doc(hidden)]
983impl crate::value::ToValue for VariantTy {
984 fn to_value(&self) -> crate::Value {
985 unsafe {
986 let mut value = crate::Value::from_type_unchecked(VariantTy::static_type());
987 gobject_ffi::g_value_set_boxed(
988 value.to_glib_none_mut().0,
989 self.to_glib_none().0 as *mut _,
990 );
991 value
992 }
993 }
994
995 fn value_type(&self) -> crate::Type {
996 VariantTy::static_type()
997 }
998}
999
1000#[doc(hidden)]
1001impl crate::value::ToValue for &VariantTy {
1002 fn to_value(&self) -> crate::Value {
1003 (*self).to_value()
1004 }
1005
1006 #[inline]
1007 fn value_type(&self) -> crate::Type {
1008 VariantTy::static_type()
1009 }
1010}
1011
1012#[doc(hidden)]
1013impl crate::value::ToValueOptional for &VariantTy {
1014 fn to_value_optional(s: Option<&Self>) -> crate::Value {
1015 let mut value = crate::Value::for_value_type::<VariantType>();
1016 unsafe {
1017 gobject_ffi::g_value_set_boxed(
1018 value.to_glib_none_mut().0,
1019 s.to_glib_none().0 as *mut _,
1020 );
1021 }
1022
1023 value
1024 }
1025}
1026
1027impl StaticType for VariantType {
1028 #[inline]
1029 fn static_type() -> Type {
1030 unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
1031 }
1032}
1033
1034#[doc(hidden)]
1035impl crate::value::ValueType for VariantType {
1036 type Type = VariantType;
1037}
1038
1039#[doc(hidden)]
1040impl crate::value::ValueTypeOptional for VariantType {}
1041
1042#[doc(hidden)]
1043unsafe impl<'a> crate::value::FromValue<'a> for VariantType {
1044 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
1045
1046 unsafe fn from_value(value: &'a crate::Value) -> Self {
1047 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
1048 debug_assert!(!ptr.is_null());
1049 from_glib_none(ptr as *const ffi::GVariantType)
1050 }
1051}
1052
1053#[doc(hidden)]
1054impl crate::value::ToValue for VariantType {
1055 fn to_value(&self) -> crate::Value {
1056 unsafe {
1057 let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
1058 gobject_ffi::g_value_set_boxed(
1059 value.to_glib_none_mut().0,
1060 ToGlibPtr::<*mut _>::to_glib_none(&self).0 as *mut _,
1061 );
1062 value
1063 }
1064 }
1065
1066 fn value_type(&self) -> crate::Type {
1067 VariantType::static_type()
1068 }
1069}
1070
1071#[doc(hidden)]
1072impl From<VariantType> for crate::Value {
1073 fn from(t: VariantType) -> Self {
1074 unsafe {
1075 let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
1076 gobject_ffi::g_value_take_boxed(
1077 value.to_glib_none_mut().0,
1078 IntoGlibPtr::<*mut _>::into_glib_ptr(t) as *mut _,
1079 );
1080 value
1081 }
1082 }
1083}
1084
1085#[doc(hidden)]
1086impl crate::value::ToValueOptional for VariantType {
1087 fn to_value_optional(s: Option<&Self>) -> crate::Value {
1088 let mut value = crate::Value::for_value_type::<Self>();
1089 unsafe {
1090 gobject_ffi::g_value_set_boxed(
1091 value.to_glib_none_mut().0,
1092 ToGlibPtr::<*mut _>::to_glib_none(&s).0 as *mut _,
1093 );
1094 }
1095
1096 value
1097 }
1098}
1099
1100impl PartialEq for VariantType {
1101 #[inline]
1102 fn eq(&self, other: &Self) -> bool {
1103 <VariantTy as PartialEq>::eq(self, other)
1104 }
1105}
1106
1107macro_rules! impl_eq {
1108 ($lhs:ty, $rhs: ty) => {
1109 #[allow(clippy::extra_unused_lifetimes)]
1110 impl<'a, 'b> PartialEq<$rhs> for $lhs {
1111 #[inline]
1112 fn eq(&self, other: &$rhs) -> bool {
1113 <VariantTy as PartialEq>::eq(self, other)
1114 }
1115 }
1116
1117 #[allow(clippy::extra_unused_lifetimes)]
1118 impl<'a, 'b> PartialEq<$lhs> for $rhs {
1119 #[inline]
1120 fn eq(&self, other: &$lhs) -> bool {
1121 <VariantTy as PartialEq>::eq(self, other)
1122 }
1123 }
1124 };
1125}
1126
1127impl_eq!(VariantType, VariantTy);
1128impl_eq!(VariantType, &'a VariantTy);
1129impl_eq!(VariantType, Cow<'a, VariantTy>);
1130impl_eq!(&'a VariantTy, Cow<'b, VariantTy>);
1131
1132macro_rules! impl_str_eq {
1133 ($lhs:ty, $rhs: ty) => {
1134 #[allow(clippy::redundant_slicing)]
1135 #[allow(clippy::extra_unused_lifetimes)]
1136 impl<'a, 'b> PartialEq<$rhs> for $lhs {
1137 #[inline]
1138 fn eq(&self, other: &$rhs) -> bool {
1139 self.as_str().eq(&other[..])
1140 }
1141 }
1142
1143 #[allow(clippy::extra_unused_lifetimes)]
1144 impl<'a, 'b> PartialEq<$lhs> for $rhs {
1145 #[inline]
1146 fn eq(&self, other: &$lhs) -> bool {
1147 self[..].eq(other.as_str())
1148 }
1149 }
1150 };
1151}
1152
1153impl_str_eq!(VariantTy, str);
1154impl_str_eq!(VariantTy, &'a str);
1155impl_str_eq!(&'a VariantTy, str);
1156impl_str_eq!(VariantTy, String);
1157impl_str_eq!(&'a VariantTy, String);
1158impl_str_eq!(VariantType, str);
1159impl_str_eq!(VariantType, &'a str);
1160impl_str_eq!(VariantType, String);
1161
1162impl Eq for VariantType {}
1163
1164#[derive(Debug, Copy, Clone)]
1169pub struct VariantTyIterator<'a> {
1170 elem: Option<&'a VariantTy>,
1171}
1172
1173impl<'a> VariantTyIterator<'a> {
1174 pub fn new(ty: &'a VariantTy) -> Result<Self, BoolError> {
1180 if (ty.is_tuple() && ty != VariantTy::TUPLE) || ty.is_dict_entry() {
1181 Ok(Self { elem: ty.first() })
1182 } else {
1183 Err(bool_error!(
1184 "Expected a definite tuple or dictionary entry type"
1185 ))
1186 }
1187 }
1188}
1189
1190impl<'a> Iterator for VariantTyIterator<'a> {
1191 type Item = &'a VariantTy;
1192
1193 #[doc(alias = "g_variant_type_next")]
1194 fn next(&mut self) -> Option<Self::Item> {
1195 let elem = self.elem?;
1196 self.elem = elem.next();
1197 Some(elem)
1198 }
1199}
1200
1201impl iter::FusedIterator for VariantTyIterator<'_> {}
1202
1203#[cfg(test)]
1204mod tests {
1205 use super::*;
1206
1207 unsafe fn equal<T, U>(ptr1: *const T, ptr2: *const U) -> bool {
1208 from_glib(ffi::g_variant_type_equal(
1209 ptr1 as *const _,
1210 ptr2 as *const _,
1211 ))
1212 }
1213
1214 #[test]
1215 fn new() {
1216 let ty = VariantTy::new("((iii)s)").unwrap();
1217 unsafe {
1218 assert!(equal(ty.as_ptr(), b"((iii)s)\0" as *const u8));
1219 }
1220 }
1221
1222 #[test]
1223 fn new_empty() {
1224 assert!(VariantTy::new("").is_err());
1225 }
1226
1227 #[test]
1228 fn new_with_nul() {
1229 assert!(VariantTy::new("((iii\0)s)").is_err());
1230 }
1231
1232 #[test]
1233 fn new_too_short() {
1234 assert!(VariantTy::new("((iii").is_err());
1235 }
1236
1237 #[test]
1238 fn new_too_long() {
1239 assert!(VariantTy::new("(iii)s").is_err());
1240 }
1241
1242 #[test]
1243 fn eq() {
1244 let ty1 = VariantTy::new("((iii)s)").unwrap();
1245 let ty2 = VariantTy::new("((iii)s)").unwrap();
1246 assert_eq!(ty1, ty2);
1247 assert_eq!(ty1, "((iii)s)");
1248 unsafe {
1249 assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
1250 }
1251 }
1252
1253 #[test]
1254 fn ne() {
1255 let ty1 = VariantTy::new("((iii)s)").unwrap();
1256 let ty2 = VariantTy::new("((iii)o)").unwrap();
1257 assert_ne!(ty1, ty2);
1258 assert_ne!(ty1, "((iii)o)");
1259 unsafe {
1260 assert!(!equal(ty1.as_ptr(), ty2.as_ptr()));
1261 }
1262 }
1263
1264 #[test]
1265 fn from_bytes() {
1266 unsafe {
1267 let ty = VariantTy::from_ptr(b"((iii)s)" as *const u8 as *const _);
1268 assert_eq!(ty, "((iii)s)");
1269 assert!(equal(ty.as_ptr(), "((iii)s)".as_ptr()));
1270 }
1271 }
1272
1273 #[test]
1274 fn to_owned() {
1275 let ty1 = VariantTy::new("((iii)s)").unwrap();
1276 let ty2 = ty1.to_owned();
1277 assert_eq!(ty1, ty2);
1278 assert_eq!(ty2, "((iii)s)");
1279 unsafe {
1280 assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
1281 }
1282 }
1283
1284 #[test]
1285 fn value() {
1286 let ty1 = VariantType::new("*").unwrap();
1287 let tyv = ty1.to_value();
1288 let ty2 = tyv.get::<VariantType>().unwrap();
1289 assert_eq!(ty1, ty2);
1290
1291 let ty3 = VariantTy::new("*").unwrap();
1292 let tyv2 = ty3.to_value();
1293 let ty4 = tyv2.get::<VariantType>().unwrap();
1294 assert_eq!(ty3, ty4);
1295
1296 let ty5 = VariantTy::ANY;
1297 let tyv3 = ty5.to_value();
1298 let ty6 = tyv3.get::<VariantType>().unwrap();
1299 assert_eq!(ty5, ty6);
1300 }
1301
1302 #[test]
1303 fn type_() {
1304 assert_eq!(VariantTy::static_type(), VariantType::static_type())
1305 }
1306
1307 #[test]
1308 fn tuple_iter() {
1309 let ty = VariantTy::new("((iii)s)").unwrap();
1310 let types: Vec<_> = ty.tuple_types().map(|t| t.as_str()).collect();
1311 assert_eq!(&types, &["(iii)", "s"]);
1312 }
1313}