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")]
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 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 unsafe { 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 unsafe {
247 VariantTy::from_ptr(ptr).to_owned()
250 }
251 }
252}
253
254#[doc(hidden)]
255impl FromGlibPtrFull<*mut ffi::GVariantType> for VariantType {
256 #[inline]
257 unsafe fn from_glib_full(ptr: *mut ffi::GVariantType) -> VariantType {
258 unsafe {
259 debug_assert!(!ptr.is_null());
260 let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
261 VariantType {
262 ptr: ptr::NonNull::new_unchecked(ptr),
263 len,
264 }
265 }
266 }
267}
268
269#[repr(transparent)]
275#[derive(Debug, PartialEq, Eq, Hash)]
276pub struct VariantTy {
277 inner: str,
278}
279
280impl VariantTy {
281 #[doc(alias = "G_VARIANT_TYPE_BOOLEAN")]
284 pub const BOOLEAN: &'static VariantTy =
285 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BOOLEAN) };
286
287 #[doc(alias = "G_VARIANT_TYPE_BYTE")]
290 pub const BYTE: &'static VariantTy =
291 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE) };
292
293 #[doc(alias = "G_VARIANT_TYPE_INT16")]
296 pub const INT16: &'static VariantTy =
297 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT16) };
298
299 #[doc(alias = "G_VARIANT_TYPE_UINT16")]
302 pub const UINT16: &'static VariantTy =
303 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT16) };
304
305 #[doc(alias = "G_VARIANT_TYPE_INT32")]
308 pub const INT32: &'static VariantTy =
309 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT32) };
310
311 #[doc(alias = "G_VARIANT_TYPE_UINT32")]
314 pub const UINT32: &'static VariantTy =
315 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT32) };
316
317 #[doc(alias = "G_VARIANT_TYPE_INT64")]
320 pub const INT64: &'static VariantTy =
321 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_INT64) };
322
323 #[doc(alias = "G_VARIANT_TYPE_UINT64")]
326 pub const UINT64: &'static VariantTy =
327 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UINT64) };
328
329 #[doc(alias = "G_VARIANT_TYPE_DOUBLE")]
332 pub const DOUBLE: &'static VariantTy =
333 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DOUBLE) };
334
335 #[doc(alias = "G_VARIANT_TYPE_STRING")]
338 pub const STRING: &'static VariantTy =
339 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING) };
340
341 #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH")]
344 pub const OBJECT_PATH: &'static VariantTy =
345 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH) };
346
347 #[doc(alias = "G_VARIANT_TYPE_SIGNATURE")]
350 pub const SIGNATURE: &'static VariantTy =
351 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_SIGNATURE) };
352
353 #[doc(alias = "G_VARIANT_TYPE_VARIANT")]
356 pub const VARIANT: &'static VariantTy =
357 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARIANT) };
358
359 #[doc(alias = "G_VARIANT_TYPE_HANDLE")]
362 pub const HANDLE: &'static VariantTy =
363 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_HANDLE) };
364
365 #[doc(alias = "G_VARIANT_TYPE_UNIT")]
368 pub const UNIT: &'static VariantTy =
369 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_UNIT) };
370
371 #[doc(alias = "G_VARIANT_TYPE_ANY")]
374 pub const ANY: &'static VariantTy =
375 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ANY) };
376
377 #[doc(alias = "G_VARIANT_TYPE_BASIC")]
380 pub const BASIC: &'static VariantTy =
381 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BASIC) };
382
383 #[doc(alias = "G_VARIANT_TYPE_MAYBE")]
386 pub const MAYBE: &'static VariantTy =
387 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_MAYBE) };
388
389 #[doc(alias = "G_VARIANT_TYPE_ARRAY")]
392 pub const ARRAY: &'static VariantTy =
393 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_ARRAY) };
394
395 #[doc(alias = "G_VARIANT_TYPE_TUPLE")]
398 pub const TUPLE: &'static VariantTy =
399 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_TUPLE) };
400
401 #[doc(alias = "G_VARIANT_TYPE_DICT_ENTRY")]
404 pub const DICT_ENTRY: &'static VariantTy =
405 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICT_ENTRY) };
406
407 #[doc(alias = "G_VARIANT_TYPE_DICTIONARY")]
410 pub const DICTIONARY: &'static VariantTy =
411 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_DICTIONARY) };
412
413 #[doc(alias = "G_VARIANT_TYPE_STRING_ARRAY")]
416 pub const STRING_ARRAY: &'static VariantTy =
417 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_STRING_ARRAY) };
418
419 #[doc(alias = "G_VARIANT_TYPE_OBJECT_PATH_ARRAY")]
422 pub const OBJECT_PATH_ARRAY: &'static VariantTy =
423 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_OBJECT_PATH_ARRAY) };
424
425 #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING")]
428 pub const BYTE_STRING: &'static VariantTy =
429 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING) };
430
431 #[doc(alias = "G_VARIANT_TYPE_BYTE_STRING_ARRAY")]
434 pub const BYTE_STRING_ARRAY: &'static VariantTy =
435 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_BYTE_STRING_ARRAY) };
436
437 #[doc(alias = "G_VARIANT_TYPE_VARDICT")]
440 pub const VARDICT: &'static VariantTy =
441 unsafe { VariantTy::from_str_unchecked(ffi::G_VARIANT_TYPE_VARDICT) };
442
443 pub fn new(type_string: &str) -> Result<&VariantTy, BoolError> {
448 unsafe {
449 let ptr = type_string.as_ptr();
450 let limit = ptr.add(type_string.len());
451 let mut end = ptr::null();
452
453 let ok = from_glib(ffi::g_variant_type_string_scan(
454 ptr as *const _,
455 limit as *const _,
456 &mut end,
457 ));
458 if ok && end as *const _ == limit {
459 Ok(&*(type_string.as_bytes() as *const [u8] as *const VariantTy))
460 } else {
461 Err(bool_error!("Invalid type string: '{}'", type_string))
462 }
463 }
464 }
465
466 #[inline]
473 pub const unsafe fn from_str_unchecked(type_string: &str) -> &VariantTy {
474 unsafe { std::mem::transmute::<&str, &VariantTy>(type_string) }
475 }
476
477 #[doc(hidden)]
481 #[allow(clippy::cast_slice_from_raw_parts)]
482 #[inline]
483 pub unsafe fn from_ptr<'a>(ptr: *const ffi::GVariantType) -> &'a VariantTy {
484 unsafe {
485 debug_assert!(!ptr.is_null());
486 let len: usize = ffi::g_variant_type_get_string_length(ptr) as _;
487 debug_assert!(len > 0);
488 &*(slice::from_raw_parts(ptr as *const u8, len) as *const [u8] as *const VariantTy)
489 }
490 }
491
492 #[doc(hidden)]
495 #[inline]
496 pub fn as_ptr(&self) -> *const ffi::GVariantType {
497 self.inner.as_ptr() as *const _
498 }
499
500 #[inline]
503 pub fn as_str(&self) -> &str {
504 &self.inner
505 }
506
507 #[doc(alias = "g_variant_type_is_definite")]
510 pub fn is_definite(&self) -> bool {
511 unsafe { from_glib(ffi::g_variant_type_is_definite(self.to_glib_none().0)) }
512 }
513
514 #[doc(alias = "g_variant_type_is_container")]
517 pub fn is_container(&self) -> bool {
518 unsafe { from_glib(ffi::g_variant_type_is_container(self.to_glib_none().0)) }
519 }
520
521 #[doc(alias = "g_variant_type_is_basic")]
524 pub fn is_basic(&self) -> bool {
525 unsafe { from_glib(ffi::g_variant_type_is_basic(self.to_glib_none().0)) }
526 }
527
528 #[doc(alias = "g_variant_type_is_maybe")]
531 pub fn is_maybe(&self) -> bool {
532 unsafe { from_glib(ffi::g_variant_type_is_maybe(self.to_glib_none().0)) }
533 }
534
535 #[doc(alias = "g_variant_type_is_array")]
538 pub fn is_array(&self) -> bool {
539 unsafe { from_glib(ffi::g_variant_type_is_array(self.to_glib_none().0)) }
540 }
541
542 #[doc(alias = "g_variant_type_is_tuple")]
545 pub fn is_tuple(&self) -> bool {
546 unsafe { from_glib(ffi::g_variant_type_is_tuple(self.to_glib_none().0)) }
547 }
548
549 #[doc(alias = "g_variant_type_is_dict_entry")]
552 pub fn is_dict_entry(&self) -> bool {
553 unsafe { from_glib(ffi::g_variant_type_is_dict_entry(self.to_glib_none().0)) }
554 }
555
556 #[doc(alias = "g_variant_type_is_variant")]
559 pub fn is_variant(&self) -> bool {
560 unsafe { from_glib(ffi::g_variant_type_is_variant(self.to_glib_none().0)) }
561 }
562
563 #[doc(alias = "g_variant_type_is_subtype_of")]
566 pub fn is_subtype_of(&self, supertype: &Self) -> bool {
567 unsafe {
568 from_glib(ffi::g_variant_type_is_subtype_of(
569 self.to_glib_none().0,
570 supertype.to_glib_none().0,
571 ))
572 }
573 }
574
575 #[doc(alias = "g_variant_type_element")]
582 pub fn element(&self) -> &VariantTy {
583 assert!(self.is_array() || self.is_maybe());
584
585 unsafe {
586 let element = ffi::g_variant_type_element(self.to_glib_none().0);
587 Self::from_ptr(element)
588 }
589 }
590
591 pub fn tuple_types(&self) -> VariantTyIterator<'_> {
598 VariantTyIterator::new(self).expect("VariantTy does not represent a tuple")
599 }
600
601 #[doc(alias = "g_variant_type_first")]
608 pub fn first(&self) -> Option<&VariantTy> {
609 assert!(self.as_str().starts_with('(') || self.as_str().starts_with('{'));
610
611 unsafe {
612 let first = ffi::g_variant_type_first(self.to_glib_none().0);
613 if first.is_null() {
614 None
615 } else {
616 Some(Self::from_ptr(first))
617 }
618 }
619 }
620
621 #[doc(alias = "g_variant_type_next")]
624 pub fn next(&self) -> Option<&VariantTy> {
625 unsafe {
626 let next = ffi::g_variant_type_next(self.to_glib_none().0);
627 if next.is_null() {
628 None
629 } else {
630 Some(Self::from_ptr(next))
631 }
632 }
633 }
634
635 #[doc(alias = "g_variant_type_n_items")]
638 pub fn n_items(&self) -> usize {
639 unsafe { ffi::g_variant_type_n_items(self.to_glib_none().0) }
640 }
641
642 #[doc(alias = "g_variant_type_key")]
649 pub fn key(&self) -> &VariantTy {
650 assert!(self.as_str().starts_with('{'));
651
652 unsafe {
653 let key = ffi::g_variant_type_key(self.to_glib_none().0);
654 Self::from_ptr(key)
655 }
656 }
657
658 #[doc(alias = "g_variant_type_value")]
665 pub fn value(&self) -> &VariantTy {
666 assert!(self.as_str().starts_with('{'));
667
668 unsafe {
669 let value = ffi::g_variant_type_value(self.to_glib_none().0);
670 Self::from_ptr(value)
671 }
672 }
673
674 pub(crate) fn as_array<'a>(&self) -> Cow<'a, VariantTy> {
677 if self == VariantTy::STRING {
678 Cow::Borrowed(VariantTy::STRING_ARRAY)
679 } else if self == VariantTy::BYTE {
680 Cow::Borrowed(VariantTy::BYTE_STRING)
681 } else if self == VariantTy::BYTE_STRING {
682 Cow::Borrowed(VariantTy::BYTE_STRING_ARRAY)
683 } else if self == VariantTy::OBJECT_PATH {
684 Cow::Borrowed(VariantTy::OBJECT_PATH_ARRAY)
685 } else if self == VariantTy::DICT_ENTRY {
686 Cow::Borrowed(VariantTy::DICTIONARY)
687 } else {
688 Cow::Owned(VariantType::new_array(self))
689 }
690 }
691}
692
693unsafe impl Sync for VariantTy {}
694
695#[doc(hidden)]
696impl<'a> ToGlibPtr<'a, *const ffi::GVariantType> for VariantTy {
697 type Storage = PhantomData<&'a Self>;
698
699 #[inline]
700 fn to_glib_none(&'a self) -> Stash<'a, *const ffi::GVariantType, Self> {
701 Stash(self.as_ptr(), PhantomData)
702 }
703}
704
705impl fmt::Display for VariantTy {
706 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
707 f.write_str(self.as_str())
708 }
709}
710
711impl<'a> From<&'a VariantTy> for Cow<'a, VariantTy> {
712 #[inline]
713 fn from(ty: &'a VariantTy) -> Cow<'a, VariantTy> {
714 Cow::Borrowed(ty)
715 }
716}
717
718impl AsRef<VariantTy> for VariantTy {
719 #[inline]
720 fn as_ref(&self) -> &Self {
721 self
722 }
723}
724
725impl ToOwned for VariantTy {
726 type Owned = VariantType;
727
728 #[inline]
729 fn to_owned(&self) -> VariantType {
730 unsafe {
731 VariantType {
732 ptr: ptr::NonNull::new_unchecked(ffi::g_variant_type_copy(self.as_ptr())),
733 len: self.inner.len(),
734 }
735 }
736 }
737}
738
739impl StaticType for VariantTy {
740 #[inline]
741 fn static_type() -> Type {
742 unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
743 }
744}
745
746#[doc(hidden)]
747unsafe impl<'a> crate::value::FromValue<'a> for &'a VariantTy {
748 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
749
750 unsafe fn from_value(value: &'a crate::Value) -> Self {
751 unsafe {
752 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
753 debug_assert!(!ptr.is_null());
754 VariantTy::from_ptr(ptr as *const ffi::GVariantType)
755 }
756 }
757}
758
759#[doc(hidden)]
760impl crate::value::ToValue for VariantTy {
761 fn to_value(&self) -> crate::Value {
762 unsafe {
763 let mut value = crate::Value::from_type_unchecked(VariantTy::static_type());
764 gobject_ffi::g_value_set_boxed(
765 value.to_glib_none_mut().0,
766 self.to_glib_none().0 as *mut _,
767 );
768 value
769 }
770 }
771
772 fn value_type(&self) -> crate::Type {
773 VariantTy::static_type()
774 }
775}
776
777#[doc(hidden)]
778impl crate::value::ToValue for &VariantTy {
779 fn to_value(&self) -> crate::Value {
780 (*self).to_value()
781 }
782
783 #[inline]
784 fn value_type(&self) -> crate::Type {
785 VariantTy::static_type()
786 }
787}
788
789#[doc(hidden)]
790impl crate::value::ToValueOptional for &VariantTy {
791 fn to_value_optional(s: Option<&Self>) -> crate::Value {
792 let mut value = crate::Value::for_value_type::<VariantType>();
793 unsafe {
794 gobject_ffi::g_value_set_boxed(
795 value.to_glib_none_mut().0,
796 s.to_glib_none().0 as *mut _,
797 );
798 }
799
800 value
801 }
802}
803
804impl StaticType for VariantType {
805 #[inline]
806 fn static_type() -> Type {
807 unsafe { from_glib(ffi::g_variant_type_get_gtype()) }
808 }
809}
810
811#[doc(hidden)]
812impl crate::value::ValueType for VariantType {
813 type Type = VariantType;
814}
815
816#[doc(hidden)]
817impl crate::value::ValueTypeOptional for VariantType {}
818
819#[doc(hidden)]
820unsafe impl<'a> crate::value::FromValue<'a> for VariantType {
821 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
822
823 unsafe fn from_value(value: &'a crate::Value) -> Self {
824 unsafe {
825 let ptr = gobject_ffi::g_value_get_boxed(value.to_glib_none().0);
826 debug_assert!(!ptr.is_null());
827 from_glib_none(ptr as *const ffi::GVariantType)
828 }
829 }
830}
831
832#[doc(hidden)]
833impl crate::value::ToValue for VariantType {
834 fn to_value(&self) -> crate::Value {
835 unsafe {
836 let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
837 gobject_ffi::g_value_set_boxed(
838 value.to_glib_none_mut().0,
839 ToGlibPtr::<*mut _>::to_glib_none(&self).0 as *mut _,
840 );
841 value
842 }
843 }
844
845 fn value_type(&self) -> crate::Type {
846 VariantType::static_type()
847 }
848}
849
850#[doc(hidden)]
851impl From<VariantType> for crate::Value {
852 fn from(t: VariantType) -> Self {
853 unsafe {
854 let mut value = crate::Value::from_type_unchecked(VariantType::static_type());
855 gobject_ffi::g_value_take_boxed(
856 value.to_glib_none_mut().0,
857 IntoGlibPtr::<*mut _>::into_glib_ptr(t) as *mut _,
858 );
859 value
860 }
861 }
862}
863
864#[doc(hidden)]
865impl crate::value::ToValueOptional for VariantType {
866 fn to_value_optional(s: Option<&Self>) -> crate::Value {
867 let mut value = crate::Value::for_value_type::<Self>();
868 unsafe {
869 gobject_ffi::g_value_set_boxed(
870 value.to_glib_none_mut().0,
871 ToGlibPtr::<*mut _>::to_glib_none(&s).0 as *mut _,
872 );
873 }
874
875 value
876 }
877}
878
879impl PartialEq for VariantType {
880 #[inline]
881 fn eq(&self, other: &Self) -> bool {
882 <VariantTy as PartialEq>::eq(self, other)
883 }
884}
885
886macro_rules! impl_eq {
887 ($lhs:ty, $rhs: ty) => {
888 #[allow(clippy::extra_unused_lifetimes)]
889 impl<'a, 'b> PartialEq<$rhs> for $lhs {
890 #[inline]
891 fn eq(&self, other: &$rhs) -> bool {
892 <VariantTy as PartialEq>::eq(self, other)
893 }
894 }
895
896 #[allow(clippy::extra_unused_lifetimes)]
897 impl<'a, 'b> PartialEq<$lhs> for $rhs {
898 #[inline]
899 fn eq(&self, other: &$lhs) -> bool {
900 <VariantTy as PartialEq>::eq(self, other)
901 }
902 }
903 };
904}
905
906impl_eq!(VariantType, VariantTy);
907impl_eq!(VariantType, &'a VariantTy);
908impl_eq!(VariantType, Cow<'a, VariantTy>);
909impl_eq!(&'a VariantTy, Cow<'b, VariantTy>);
910
911macro_rules! impl_str_eq {
912 ($lhs:ty, $rhs: ty) => {
913 #[allow(clippy::redundant_slicing)]
914 #[allow(clippy::extra_unused_lifetimes)]
915 impl<'a, 'b> PartialEq<$rhs> for $lhs {
916 #[inline]
917 fn eq(&self, other: &$rhs) -> bool {
918 self.as_str().eq(&other[..])
919 }
920 }
921
922 #[allow(clippy::extra_unused_lifetimes)]
923 impl<'a, 'b> PartialEq<$lhs> for $rhs {
924 #[inline]
925 fn eq(&self, other: &$lhs) -> bool {
926 self[..].eq(other.as_str())
927 }
928 }
929 };
930}
931
932impl_str_eq!(VariantTy, str);
933impl_str_eq!(VariantTy, &'a str);
934impl_str_eq!(&'a VariantTy, str);
935impl_str_eq!(VariantTy, String);
936impl_str_eq!(&'a VariantTy, String);
937impl_str_eq!(VariantType, str);
938impl_str_eq!(VariantType, &'a str);
939impl_str_eq!(VariantType, String);
940
941impl Eq for VariantType {}
942
943#[derive(Debug, Copy, Clone)]
948pub struct VariantTyIterator<'a> {
949 elem: Option<&'a VariantTy>,
950}
951
952impl<'a> VariantTyIterator<'a> {
953 pub fn new(ty: &'a VariantTy) -> Result<Self, BoolError> {
959 if (ty.is_tuple() && ty != VariantTy::TUPLE) || ty.is_dict_entry() {
960 Ok(Self { elem: ty.first() })
961 } else {
962 Err(bool_error!(
963 "Expected a definite tuple or dictionary entry type"
964 ))
965 }
966 }
967}
968
969impl<'a> Iterator for VariantTyIterator<'a> {
970 type Item = &'a VariantTy;
971
972 #[doc(alias = "g_variant_type_next")]
973 fn next(&mut self) -> Option<Self::Item> {
974 let elem = self.elem?;
975 self.elem = elem.next();
976 Some(elem)
977 }
978}
979
980impl iter::FusedIterator for VariantTyIterator<'_> {}
981
982#[cfg(test)]
983mod tests {
984 use super::*;
985
986 unsafe fn equal<T, U>(ptr1: *const T, ptr2: *const U) -> bool {
987 unsafe {
988 from_glib(ffi::g_variant_type_equal(
989 ptr1 as *const _,
990 ptr2 as *const _,
991 ))
992 }
993 }
994
995 #[test]
996 fn new() {
997 let ty = VariantTy::new("((iii)s)").unwrap();
998 unsafe {
999 assert!(equal(ty.as_ptr(), b"((iii)s)\0" as *const u8));
1000 }
1001 }
1002
1003 #[test]
1004 fn new_empty() {
1005 assert!(VariantTy::new("").is_err());
1006 }
1007
1008 #[test]
1009 fn new_with_nul() {
1010 assert!(VariantTy::new("((iii\0)s)").is_err());
1011 }
1012
1013 #[test]
1014 fn new_too_short() {
1015 assert!(VariantTy::new("((iii").is_err());
1016 }
1017
1018 #[test]
1019 fn new_too_long() {
1020 assert!(VariantTy::new("(iii)s").is_err());
1021 }
1022
1023 #[test]
1024 fn eq() {
1025 let ty1 = VariantTy::new("((iii)s)").unwrap();
1026 let ty2 = VariantTy::new("((iii)s)").unwrap();
1027 assert_eq!(ty1, ty2);
1028 assert_eq!(ty1, "((iii)s)");
1029 unsafe {
1030 assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
1031 }
1032 }
1033
1034 #[test]
1035 fn ne() {
1036 let ty1 = VariantTy::new("((iii)s)").unwrap();
1037 let ty2 = VariantTy::new("((iii)o)").unwrap();
1038 assert_ne!(ty1, ty2);
1039 assert_ne!(ty1, "((iii)o)");
1040 unsafe {
1041 assert!(!equal(ty1.as_ptr(), ty2.as_ptr()));
1042 }
1043 }
1044
1045 #[test]
1046 fn from_bytes() {
1047 unsafe {
1048 let ty = VariantTy::from_ptr(b"((iii)s)" as *const u8 as *const _);
1049 assert_eq!(ty, "((iii)s)");
1050 assert!(equal(ty.as_ptr(), "((iii)s)".as_ptr()));
1051 }
1052 }
1053
1054 #[test]
1055 fn to_owned() {
1056 let ty1 = VariantTy::new("((iii)s)").unwrap();
1057 let ty2 = ty1.to_owned();
1058 assert_eq!(ty1, ty2);
1059 assert_eq!(ty2, "((iii)s)");
1060 unsafe {
1061 assert!(equal(ty1.as_ptr(), ty2.as_ptr()));
1062 }
1063 }
1064
1065 #[test]
1066 fn value() {
1067 let ty1 = VariantType::new("*").unwrap();
1068 let tyv = ty1.to_value();
1069 let ty2 = tyv.get::<VariantType>().unwrap();
1070 assert_eq!(ty1, ty2);
1071
1072 let ty3 = VariantTy::new("*").unwrap();
1073 let tyv2 = ty3.to_value();
1074 let ty4 = tyv2.get::<VariantType>().unwrap();
1075 assert_eq!(ty3, ty4);
1076
1077 let ty5 = VariantTy::ANY;
1078 let tyv3 = ty5.to_value();
1079 let ty6 = tyv3.get::<VariantType>().unwrap();
1080 assert_eq!(ty5, ty6);
1081 }
1082
1083 #[test]
1084 fn type_() {
1085 assert_eq!(VariantTy::static_type(), VariantType::static_type())
1086 }
1087
1088 #[test]
1089 fn tuple_iter() {
1090 let ty = VariantTy::new("((iii)s)").unwrap();
1091 let types: Vec<_> = ty.tuple_types().map(|t| t.as_str()).collect();
1092 assert_eq!(&types, &["(iii)", "s"]);
1093 }
1094}