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")]
24pub struct VariantType {
25 ptr: ptr::NonNull<ffi::GVariantType>,
28 len: usize,
31}
32
33impl VariantType {
34 pub fn new(type_string: &str) -> Result<VariantType, BoolError> {
39 VariantTy::new(type_string).map(ToOwned::to_owned)
40 }
41
42 #[doc(alias = "g_variant_type_new_dict_entry")]
45 pub fn new_dict_entry(key_type: &VariantTy, value_type: &VariantTy) -> VariantType {
46 unsafe {
47 from_glib_full(ffi::g_variant_type_new_dict_entry(
48 key_type.to_glib_none().0,
49 value_type.to_glib_none().0,
50 ))
51 }
52 }
53
54 #[doc(alias = "g_variant_type_new_array")]
57 pub fn new_array(elem_type: &VariantTy) -> VariantType {
58 unsafe { from_glib_full(ffi::g_variant_type_new_array(elem_type.to_glib_none().0)) }
59 }
60
61 #[doc(alias = "g_variant_type_new_maybe")]
64 pub fn new_maybe(child_type: &VariantTy) -> VariantType {
65 unsafe { from_glib_full(ffi::g_variant_type_new_maybe(child_type.to_glib_none().0)) }
66 }
67
68 #[doc(alias = "g_variant_type_new_tuple")]
71 pub fn new_tuple(items: impl IntoIterator<Item = impl AsRef<VariantTy>>) -> VariantType {
72 let mut builder = crate::GStringBuilder::new("(");
73
74 for ty in items {
75 builder.append(ty.as_ref().as_str());
76 }
77
78 builder.append_c(')');
79
80 VariantType::from_string(builder.into_string()).unwrap()
81 }
82
83 pub fn from_string(type_string: impl Into<crate::GString>) -> Result<VariantType, BoolError> {
88 let type_string = type_string.into();
89 VariantTy::new(&type_string)?;
90
91 let len = type_string.len();
92 unsafe {
93 let ptr = type_string.into_glib_ptr();
94
95 Ok(VariantType {
96 ptr: ptr::NonNull::new_unchecked(ptr as *mut ffi::GVariantType),
97 len,
98 })
99 }
100 }
101}
102
103unsafe impl Send for VariantType {}
104unsafe impl Sync for VariantType {}
105
106impl Drop for VariantType {
107 #[inline]
108 fn drop(&mut self) {
109 unsafe { ffi::g_variant_type_free(self.ptr.as_ptr()) }
110 }
111}
112
113impl AsRef<VariantTy> for VariantType {
114 #[inline]
115 fn as_ref(&self) -> &VariantTy {
116 self
117 }
118}
119
120impl Borrow<VariantTy> for VariantType {
121 #[inline]
122 fn borrow(&self) -> &VariantTy {
123 self
124 }
125}
126
127impl Clone for VariantType {
128 #[inline]
129 fn clone(&self) -> VariantType {
130 unsafe {
131 VariantType {
132 ptr: ptr::NonNull::new_unchecked(ffi::g_variant_type_copy(self.ptr.as_ptr())),
133 len: self.len,
134 }
135 }
136 }
137}
138
139impl Deref for VariantType {
140 type Target = VariantTy;
141
142 #[allow(clippy::cast_slice_from_raw_parts)]
143 #[inline]
144 fn deref(&self) -> &VariantTy {
145 unsafe {
146 &*(slice::from_raw_parts(self.ptr.as_ptr() as *const u8, self.len) as *const [u8]
147 as *const VariantTy)
148 }
149 }
150}
151
152impl fmt::Debug for VariantType {
153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154 <VariantTy as fmt::Debug>::fmt(self, f)
155 }
156}
157
158impl fmt::Display for VariantType {
159 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160 f.write_str(self.as_str())
161 }
162}
163
164impl FromStr for VariantType {
165 type Err = BoolError;
166
167 fn from_str(s: &str) -> Result<Self, Self::Err> {
168 Self::new(s)
169 }
170}
171
172impl Hash for VariantType {
173 #[inline]
174 fn hash<H: Hasher>(&self, state: &mut H) {
175 <VariantTy as Hash>::hash(self, state)
176 }
177}
178
179impl<'a> From<VariantType> for Cow<'a, VariantTy> {
180 #[inline]
181 fn from(ty: VariantType) -> Cow<'a, VariantTy> {
182 Cow::Owned(ty)
183 }
184}
185
186#[doc(hidden)]
187impl IntoGlibPtr<*mut ffi::GVariantType> for VariantType {
188 #[inline]
189 unsafe fn into_glib_ptr(self) -> *mut ffi::GVariantType {
190 std::mem::ManuallyDrop::new(self).to_glib_none().0
191 }
192}
193
194#[doc(hidden)]
195impl<'a> ToGlibPtr<'a, *const ffi::GVariantType> for VariantType {
196 type Storage = PhantomData<&'a Self>;
197
198 #[inline]
199 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GVariantType, Self> {
200 Stash(self.ptr.as_ptr(), PhantomData)
201 }
202
203 #[inline]
204 fn to_glib_full(&self) -> *const ffi::GVariantType {
205 unsafe { ffi::g_variant_type_copy(self.ptr.as_ptr()) }
206 }
207}
208
209#[doc(hidden)]
210impl<'a> ToGlibPtr<'a, *mut ffi::GVariantType> for VariantType {
211 type Storage = PhantomData<&'a Self>;
212
213 #[inline]
214 fn to_glib_none(&'a self) -> Stash<'a, *mut ffi::GVariantType, Self> {
215 Stash(self.ptr.as_ptr(), PhantomData)
216 }
217
218 #[inline]
219 fn to_glib_full(&self) -> *mut ffi::GVariantType {
220 unsafe { ffi::g_variant_type_copy(self.ptr.as_ptr()) }
221 }
222}
223
224#[doc(hidden)]
225impl<'a> ToGlibPtrMut<'a, *mut ffi::GVariantType> for VariantType {
226 type Storage = PhantomData<&'a mut Self>;
227
228 #[inline]
229 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::GVariantType, Self> {
230 StashMut(self.ptr.as_ptr(), PhantomData)
231 }
232}
233
234#[doc(hidden)]
235impl FromGlibPtrNone<*const ffi::GVariantType> for VariantType {
236 #[inline]
237 unsafe fn from_glib_none(ptr: *const ffi::GVariantType) -> VariantType {
238 VariantTy::from_ptr(ptr).to_owned()
239 }
240}
241
242#[doc(hidden)]
243impl FromGlibPtrFull<*const ffi::GVariantType> for VariantType {
244 #[inline]
245 unsafe fn from_glib_full(ptr: *const ffi::GVariantType) -> VariantType {
246 VariantTy::from_ptr(ptr).to_owned()
249 }
250}
251
252#[doc(hidden)]
253impl FromGlibPtrFull<*mut ffi::GVariantType> for VariantType {
254 #[inline]
255 unsafe fn from_glib_full(ptr: *mut ffi::GVariantType) -> VariantType {
256 debug_assert!(!ptr.is_null());
257 let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
258 VariantType {
259 ptr: ptr::NonNull::new_unchecked(ptr),
260 len,
261 }
262 }
263}
264
265#[repr(transparent)]
271#[derive(Debug, PartialEq, Eq, Hash)]
272pub struct VariantTy {
273 inner: str,
274}
275
276impl VariantTy {
277 #[doc(alias = "G_VARIANT_TYPE_BOOLEAN")]
280 pub const BOOLEAN: &'static VariantTy =
281 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BOOLEAN) };
282
283 #[doc(alias = "G_VARIANT_TYPE_BYTE")]
286 pub const BYTE: &'static VariantTy =
287 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE) };
288
289 #[doc(alias = "G_VARIANT_TYPE_INT16")]
292 pub const INT16: &'static VariantTy =
293 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT16) };
294
295 #[doc(alias = "G_VARIANT_TYPE_UINT16")]
298 pub const UINT16: &'static VariantTy =
299 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT16) };
300
301 #[doc(alias = "G_VARIANT_TYPE_INT32")]
304 pub const INT32: &'static VariantTy =
305 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT32) };
306
307 #[doc(alias = "G_VARIANT_TYPE_UINT32")]
310 pub const UINT32: &'static VariantTy =
311 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT32) };
312
313 #[doc(alias = "G_VARIANT_TYPE_INT64")]
316 pub const INT64: &'static VariantTy =
317 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT64) };
318
319 #[doc(alias = "G_VARIANT_TYPE_UINT64")]
322 pub const UINT64: &'static VariantTy =
323 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT64) };
324
325 #[doc(alias = "G_VARIANT_TYPE_DOUBLE")]
328 pub const DOUBLE: &'static VariantTy =
329 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DOUBLE) };
330
331 #[doc(alias = "G_VARIANT_TYPE_STRING")]
334 pub const STRING: &'static VariantTy =
335 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING) };
336
337 #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH")]
340 pub const OBJECT_PATH: &'static VariantTy =
341 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH) };
342
343 #[doc(alias = "G_VARIANT_TYPE_SIGNATURE")]
346 pub const SIGNATURE: &'static VariantTy =
347 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_SIGNATURE) };
348
349 #[doc(alias = "G_VARIANT_TYPE_VARIANT")]
352 pub const VARIANT: &'static VariantTy =
353 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARIANT) };
354
355 #[doc(alias = "G_VARIANT_TYPE_HANDLE")]
358 pub const HANDLE: &'static VariantTy =
359 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_HANDLE) };
360
361 #[doc(alias = "G_VARIANT_TYPE_UNIT")]
364 pub const UNIT: &'static VariantTy =
365 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UNIT) };
366
367 #[doc(alias = "G_VARIANT_TYPE_ANY")]
370 pub const ANY: &'static VariantTy =
371 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ANY) };
372
373 #[doc(alias = "G_VARIANT_TYPE_BASIC")]
376 pub const BASIC: &'static VariantTy =
377 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BASIC) };
378
379 #[doc(alias = "G_VARIANT_TYPE_MAYBE")]
382 pub const MAYBE: &'static VariantTy =
383 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_MAYBE) };
384
385 #[doc(alias = "G_VARIANT_TYPE_ARRAY")]
388 pub const ARRAY: &'static VariantTy =
389 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ARRAY) };
390
391 #[doc(alias = "G_VARIANT_TYPE_TUPLE")]
394 pub const TUPLE: &'static VariantTy =
395 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_TUPLE) };
396
397 #[doc(alias = "G_VARIANT_TYPE_DICT_ENTRY")]
400 pub const DICT_ENTRY: &'static VariantTy =
401 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICT_ENTRY) };
402
403 #[doc(alias = "G_VARIANT_TYPE_DICTIONARY")]
406 pub const DICTIONARY: &'static VariantTy =
407 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICTIONARY) };
408
409 #[doc(alias = "G_VARIANT_TYPE_STRING_ARRAY")]
412 pub const STRING_ARRAY: &'static VariantTy =
413 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING_ARRAY) };
414
415 #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH_ARRAY")]
418 pub const OBJECT_PATH_ARRAY: &'static VariantTy =
419 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH_ARRAY) };
420
421 #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING")]
424 pub const BYTE_STRING: &'static VariantTy =
425 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING) };
426
427 #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING_ARRAY")]
430 pub const BYTE_STRING_ARRAY: &'static VariantTy =
431 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING_ARRAY) };
432
433 #[doc(alias = "G_VARIANT_TYPE_VARDICT")]
436 pub const VARDICT: &'static VariantTy =
437 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARDICT) };
438
439 pub fn new(type_string: &str) -> Result<&VariantTy, BoolError> {
444 unsafe {
445 let ptr = type_string.as_ptr();
446 let limit = ptr.add(type_string.len());
447 let mut end = ptr::null();
448
449 let ok = from_glib(ffi::g_variant_type_string_scan(
450 ptr as *const _,
451 limit as *const _,
452 &mut end,
453 ));
454 if ok && end as *const _ == limit {
455 Ok(&*(type_string.as_bytes() as *const [u8] as *const VariantTy))
456 } else {
457 Err(bool_error!("Invalid type string: '{}'", type_string))
458 }
459 }
460 }
461
462 #[inline]
469 pub const unsafe fn from_str_unchecked(type_string: &str) -> &VariantTy {
470 std::mem::transmute::<&str, &VariantTy>(type_string)
471 }
472
473 #[doc(hidden)]
477 #[allow(clippy::cast_slice_from_raw_parts)]
478 #[inline]
479 pub unsafe fn from_ptr<'a>(ptr: *const ffi::GVariantType) -> &'a VariantTy {
480 debug_assert!(!ptr.is_null());
481 let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
482 debug_assert!(len > 0);
483 &*(slice::from_raw_parts(ptr as *const u8, len) as *const [u8] as *const VariantTy)
484 }
485
486 #[doc(hidden)]
489 #[inline]
490 pub fn as_ptr(&self) -> *const ffi::GVariantType {
491 self.inner.as_ptr() as *const _
492 }
493
494 #[inline]
497 pub fn as_str(&self) -> &str {
498 &self.inner
499 }
500
501 #[doc(alias = "g_variant_type_is_definite")]
504 pub fn is_definite(&self) -> bool {
505 unsafe { from_glib(ffi::g_variant_type_is_definite(self.to_glib_none().0)) }
506 }
507
508 #[doc(alias = "g_variant_type_is_container")]
511 pub fn is_container(&self) -> bool {
512 unsafe { from_glib(ffi::g_variant_type_is_container(self.to_glib_none().0)) }
513 }
514
515 #[doc(alias = "g_variant_type_is_basic")]
518 pub fn is_basic(&self) -> bool {
519 unsafe { from_glib(ffi::g_variant_type_is_basic(self.to_glib_none().0)) }
520 }
521
522 #[doc(alias = "g_variant_type_is_maybe")]
525 pub fn is_maybe(&self) -> bool {
526 unsafe { from_glib(ffi::g_variant_type_is_maybe(self.to_glib_none().0)) }
527 }
528
529 #[doc(alias = "g_variant_type_is_array")]
532 pub fn is_array(&self) -> bool {
533 unsafe { from_glib(ffi::g_variant_type_is_array(self.to_glib_none().0)) }
534 }
535
536 #[doc(alias = "g_variant_type_is_tuple")]
539 pub fn is_tuple(&self) -> bool {
540 unsafe { from_glib(ffi::g_variant_type_is_tuple(self.to_glib_none().0)) }
541 }
542
543 #[doc(alias = "g_variant_type_is_dict_entry")]
546 pub fn is_dict_entry(&self) -> bool {
547 unsafe { from_glib(ffi::g_variant_type_is_dict_entry(self.to_glib_none().0)) }
548 }
549
550 #[doc(alias = "g_variant_type_is_variant")]
553 pub fn is_variant(&self) -> bool {
554 unsafe { from_glib(ffi::g_variant_type_is_variant(self.to_glib_none().0)) }
555 }
556
557 #[doc(alias = "g_variant_type_is_subtype_of")]
560 pub fn is_subtype_of(&self, supertype: &Self) -> bool {
561 unsafe {
562 from_glib(ffi::g_variant_type_is_subtype_of(
563 self.to_glib_none().0,
564 supertype.to_glib_none().0,
565 ))
566 }
567 }
568
569 #[doc(alias = "g_variant_type_element")]
576 pub fn element(&self) -> &VariantTy {
577 assert!(self.is_array() || self.is_maybe());
578
579 unsafe {
580 let element = ffi::g_variant_type_element(self.to_glib_none().0);
581 Self::from_ptr(element)
582 }
583 }
584
585 pub fn tuple_types(&self) -> VariantTyIterator {
592 VariantTyIterator::new(self).expect("VariantTy does not represent a tuple")
593 }
594
595 #[doc(alias = "g_variant_type_first")]
602 pub fn first(&self) -> Option<&VariantTy> {
603 assert!(self.as_str().starts_with('(') || self.as_str().starts_with('{'));
604
605 unsafe {
606 let first = ffi::g_variant_type_first(self.to_glib_none().0);
607 if first.is_null() {
608 None
609 } else {
610 Some(Self::from_ptr(first))
611 }
612 }
613 }
614
615 #[doc(alias = "g_variant_type_next")]
618 pub fn next(&self) -> Option<&VariantTy> {
619 unsafe {
620 let next = ffi::g_variant_type_next(self.to_glib_none().0);
621 if next.is_null() {
622 None
623 } else {
624 Some(Self::from_ptr(next))
625 }
626 }
627 }
628
629 #[doc(alias = "g_variant_type_n_items")]
632 pub fn n_items(&self) -> usize {
633 unsafe { ffi::g_variant_type_n_items(self.to_glib_none().0) }
634 }
635
636 #[doc(alias = "g_variant_type_key")]
643 pub fn key(&self) -> &VariantTy {
644 assert!(self.as_str().starts_with('{'));
645
646 unsafe {
647 let key = ffi::g_variant_type_key(self.to_glib_none().0);
648 Self::from_ptr(key)
649 }
650 }
651
652 #[doc(alias = "g_variant_type_value")]
659 pub fn value(&self) -> &VariantTy {
660 assert!(self.as_str().starts_with('{'));
661
662 unsafe {
663 let value = ffi::g_variant_type_value(self.to_glib_none().0);
664 Self::from_ptr(value)
665 }
666 }
667
668 pub(crate) fn as_array<'a>(&self) -> Cow<'a, VariantTy> {
671 if self == VariantTy::STRING {
672 Cow::Borrowed(VariantTy::STRING_ARRAY)
673 } else if self == VariantTy::BYTE {
674 Cow::Borrowed(VariantTy::BYTE_STRING)
675 } else if self == VariantTy::BYTE_STRING {
676 Cow::Borrowed(VariantTy::BYTE_STRING_ARRAY)
677 } else if self == VariantTy::OBJECT_PATH {
678 Cow::Borrowed(VariantTy::OBJECT_PATH_ARRAY)
679 } else if self == VariantTy::DICT_ENTRY {
680 Cow::Borrowed(VariantTy::DICTIONARY)
681 } else {
682 Cow::Owned(VariantType::new_array(self))
683 }
684 }
685}
686
687unsafe impl Sync for VariantTy {}
688
689#[doc(hidden)]
690impl<'a> ToGlibPtr<'a, *const ffi::GVariantType> for VariantTy {
691 type Storage = PhantomData<&'a Self>;
692
693 #[inline]
694 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GVariantType, Self> {
695 Stash(self.as_ptr(), PhantomData)
696 }
697}
698
699impl fmt::Display for VariantTy {
700 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
701 f.write_str(self.as_str())
702 }
703}
704
705impl<'a> From<&'a VariantTy> for Cow<'a, VariantTy> {
706 #[inline]
707 fn from(ty: &'a VariantTy) -> Cow<'a, VariantTy> {
708 Cow::Borrowed(ty)
709 }
710}
711
712impl AsRef<VariantTy> for VariantTy {
713 #[inline]
714 fn as_ref(&self) -> &Self {
715 self
716 }
717}
718
719impl ToOwned for VariantTy {
720 type Owned = VariantType;
721
722 #[inline]
723 fn to_owned(&self) -> VariantType {
724 unsafe {
725 VariantType {
726 ptr: ptr::NonNull::new_unchecked(ffi::g_variant_type_copy(self.as_ptr())),
727 len: self.inner.len(),
728 }
729 }
730 }
731}
732
733impl StaticType for VariantTy {
734 #[inline]
735 fn static_type() -> Type {
736 unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
737 }
738}
739
740#[doc(hidden)]
741unsafe impl<'a> crate::value::FromValue<'a> for &'a VariantTy {
742 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
743
744 unsafe fn from_value(value: &'a crate::Value) -> Self {
745 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
746 debug_assert!(!ptr.is_null());
747 VariantTy::from_ptr(ptr as *const ffi::GVariantType)
748 }
749}
750
751#[doc(hidden)]
752impl crate::value::ToValue for VariantTy {
753 fn to_value(&self) -> crate::Value {
754 unsafe {
755 let mut value = crate::Value::from_type_unchecked(VariantTy::static_type());
756 gobject_ffi::g_value_set_boxed(
757 value.to_glib_none_mut().0,
758 self.to_glib_none().0 as *mut _,
759 );
760 value
761 }
762 }
763
764 fn value_type(&self) -> crate::Type {
765 VariantTy::static_type()
766 }
767}
768
769#[doc(hidden)]
770impl crate::value::ToValue for &VariantTy {
771 fn to_value(&self) -> crate::Value {
772 (*self).to_value()
773 }
774
775 #[inline]
776 fn value_type(&self) -> crate::Type {
777 VariantTy::static_type()
778 }
779}
780
781#[doc(hidden)]
782impl crate::value::ToValueOptional for &VariantTy {
783 fn to_value_optional(s: Option<&Self>) -> crate::Value {
784 let mut value = crate::Value::for_value_type::<VariantType>();
785 unsafe {
786 gobject_ffi::g_value_set_boxed(
787 value.to_glib_none_mut().0,
788 s.to_glib_none().0 as *mut _,
789 );
790 }
791
792 value
793 }
794}
795
796impl StaticType for VariantType {
797 #[inline]
798 fn static_type() -> Type {
799 unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
800 }
801}
802
803#[doc(hidden)]
804impl crate::value::ValueType for VariantType {
805 type Type = VariantType;
806}
807
808#[doc(hidden)]
809impl crate::value::ValueTypeOptional for VariantType {}
810
811#[doc(hidden)]
812unsafe impl<'a> crate::value::FromValue<'a> for VariantType {
813 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
814
815 unsafe fn from_value(value: &'a crate::Value) -> Self {
816 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
817 debug_assert!(!ptr.is_null());
818 from_glib_none(ptr as *const ffi::GVariantType)
819 }
820}
821
822#[doc(hidden)]
823impl crate::value::ToValue for VariantType {
824 fn to_value(&self) -> crate::Value {
825 unsafe {
826 let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
827 gobject_ffi::g_value_set_boxed(
828 value.to_glib_none_mut().0,
829 ToGlibPtr::<*mut _>::to_glib_none(&self).0 as *mut _,
830 );
831 value
832 }
833 }
834
835 fn value_type(&self) -> crate::Type {
836 VariantType::static_type()
837 }
838}
839
840#[doc(hidden)]
841impl From<VariantType> for crate::Value {
842 fn from(t: VariantType) -> Self {
843 unsafe {
844 let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
845 gobject_ffi::g_value_take_boxed(
846 value.to_glib_none_mut().0,
847 IntoGlibPtr::<*mut _>::into_glib_ptr(t) as *mut _,
848 );
849 value
850 }
851 }
852}
853
854#[doc(hidden)]
855impl crate::value::ToValueOptional for VariantType {
856 fn to_value_optional(s: Option<&Self>) -> crate::Value {
857 let mut value = crate::Value::for_value_type::<Self>();
858 unsafe {
859 gobject_ffi::g_value_set_boxed(
860 value.to_glib_none_mut().0,
861 ToGlibPtr::<*mut _>::to_glib_none(&s).0 as *mut _,
862 );
863 }
864
865 value
866 }
867}
868
869impl PartialEq for VariantType {
870 #[inline]
871 fn eq(&self, other: &Self) -> bool {
872 <VariantTy as PartialEq>::eq(self, other)
873 }
874}
875
876macro_rules! impl_eq {
877 ($lhs:ty, $rhs: ty) => {
878 #[allow(clippy::extra_unused_lifetimes)]
879 impl<'a, 'b> PartialEq<$rhs> for $lhs {
880 #[inline]
881 fn eq(&self, other: &$rhs) -> bool {
882 <VariantTy as PartialEq>::eq(self, other)
883 }
884 }
885
886 #[allow(clippy::extra_unused_lifetimes)]
887 impl<'a, 'b> PartialEq<$lhs> for $rhs {
888 #[inline]
889 fn eq(&self, other: &$lhs) -> bool {
890 <VariantTy as PartialEq>::eq(self, other)
891 }
892 }
893 };
894}
895
896impl_eq!(VariantType, VariantTy);
897impl_eq!(VariantType, &'a VariantTy);
898impl_eq!(VariantType, Cow<'a, VariantTy>);
899impl_eq!(&'a VariantTy, Cow<'b, VariantTy>);
900
901macro_rules! impl_str_eq {
902 ($lhs:ty, $rhs: ty) => {
903 #[allow(clippy::redundant_slicing)]
904 #[allow(clippy::extra_unused_lifetimes)]
905 impl<'a, 'b> PartialEq<$rhs> for $lhs {
906 #[inline]
907 fn eq(&self, other: &$rhs) -> bool {
908 self.as_str().eq(&other[..])
909 }
910 }
911
912 #[allow(clippy::extra_unused_lifetimes)]
913 impl<'a, 'b> PartialEq<$lhs> for $rhs {
914 #[inline]
915 fn eq(&self, other: &$lhs) -> bool {
916 self[..].eq(other.as_str())
917 }
918 }
919 };
920}
921
922impl_str_eq!(VariantTy, str);
923impl_str_eq!(VariantTy, &'a str);
924impl_str_eq!(&'a VariantTy, str);
925impl_str_eq!(VariantTy, String);
926impl_str_eq!(&'a VariantTy, String);
927impl_str_eq!(VariantType, str);
928impl_str_eq!(VariantType, &'a str);
929impl_str_eq!(VariantType, String);
930
931impl Eq for VariantType {}
932
933#[derive(Debug, Copy, Clone)]
938pub struct VariantTyIterator<'a> {
939 elem: Option<&'a VariantTy>,
940}
941
942impl<'a> VariantTyIterator<'a> {
943 pub fn new(ty: &'a VariantTy) -> Result<Self, BoolError> {
949 if (ty.is_tuple() && ty != VariantTy::TUPLE) || ty.is_dict_entry() {
950 Ok(Self { elem: ty.first() })
951 } else {
952 Err(bool_error!(
953 "Expected a definite tuple or dictionary entry type"
954 ))
955 }
956 }
957}
958
959impl<'a> Iterator for VariantTyIterator<'a> {
960 type Item = &'a VariantTy;
961
962 #[doc(alias = "g_variant_type_next")]
963 fn next(&mut self) -> Option<Self::Item> {
964 let elem = self.elem?;
965 self.elem = elem.next();
966 Some(elem)
967 }
968}
969
970impl iter::FusedIterator for VariantTyIterator<'_> {}
971
972#[cfg(test)]
973mod tests {
974 use super::*;
975
976 unsafe fn equal<T, U>(ptr1: *const T, ptr2: *const U) -> bool {
977 from_glib(ffi::g_variant_type_equal(
978 ptr1 as *const _,
979 ptr2 as *const _,
980 ))
981 }
982
983 #[test]
984 fn new() {
985 let ty = VariantTy::new("((iii)s)").unwrap();
986 unsafe {
987 assert!(equal(ty.as_ptr(), b"((iii)s)\0" as *const u8));
988 }
989 }
990
991 #[test]
992 fn new_empty() {
993 assert!(VariantTy::new("").is_err());
994 }
995
996 #[test]
997 fn new_with_nul() {
998 assert!(VariantTy::new("((iii\0)s)").is_err());
999 }
1000
1001 #[test]
1002 fn new_too_short() {
1003 assert!(VariantTy::new("((iii").is_err());
1004 }
1005
1006 #[test]
1007 fn new_too_long() {
1008 assert!(VariantTy::new("(iii)s").is_err());
1009 }
1010
1011 #[test]
1012 fn eq() {
1013 let ty1 = VariantTy::new("((iii)s)").unwrap();
1014 let ty2 = VariantTy::new("((iii)s)").unwrap();
1015 assert_eq!(ty1, ty2);
1016 assert_eq!(ty1, "((iii)s)");
1017 unsafe {
1018 assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
1019 }
1020 }
1021
1022 #[test]
1023 fn ne() {
1024 let ty1 = VariantTy::new("((iii)s)").unwrap();
1025 let ty2 = VariantTy::new("((iii)o)").unwrap();
1026 assert_ne!(ty1, ty2);
1027 assert_ne!(ty1, "((iii)o)");
1028 unsafe {
1029 assert!(!equal(ty1.as_ptr(), ty2.as_ptr()));
1030 }
1031 }
1032
1033 #[test]
1034 fn from_bytes() {
1035 unsafe {
1036 let ty = VariantTy::from_ptr(b"((iii)s)" as *const u8 as *const _);
1037 assert_eq!(ty, "((iii)s)");
1038 assert!(equal(ty.as_ptr(), "((iii)s)".as_ptr()));
1039 }
1040 }
1041
1042 #[test]
1043 fn to_owned() {
1044 let ty1 = VariantTy::new("((iii)s)").unwrap();
1045 let ty2 = ty1.to_owned();
1046 assert_eq!(ty1, ty2);
1047 assert_eq!(ty2, "((iii)s)");
1048 unsafe {
1049 assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
1050 }
1051 }
1052
1053 #[test]
1054 fn value() {
1055 let ty1 = VariantType::new("*").unwrap();
1056 let tyv = ty1.to_value();
1057 let ty2 = tyv.get::<VariantType>().unwrap();
1058 assert_eq!(ty1, ty2);
1059
1060 let ty3 = VariantTy::new("*").unwrap();
1061 let tyv2 = ty3.to_value();
1062 let ty4 = tyv2.get::<VariantType>().unwrap();
1063 assert_eq!(ty3, ty4);
1064
1065 let ty5 = VariantTy::ANY;
1066 let tyv3 = ty5.to_value();
1067 let ty6 = tyv3.get::<VariantType>().unwrap();
1068 assert_eq!(ty5, ty6);
1069 }
1070
1071 #[test]
1072 fn type_() {
1073 assert_eq!(VariantTy::static_type(), VariantType::static_type())
1074 }
1075
1076 #[test]
1077 fn tuple_iter() {
1078 let ty = VariantTy::new("((iii)s)").unwrap();
1079 let types: Vec<_> = ty.tuple_types().map(|t| t.as_str()).collect();
1080 assert_eq!(&types, &["(iii)", "s"]);
1081 }
1082}