1use std::{
105 borrow::Cow,
106 cmp::Ordering,
107 collections::{BTreeMap, HashMap},
108 fmt,
109 fmt::Display,
110 hash::{BuildHasher, Hash, Hasher},
111 mem, ptr, slice, str,
112};
113
114use crate::{
115 ffi, gobject_ffi, prelude::*, translate::*, Bytes, Type, VariantIter, VariantStrIter,
116 VariantTy, VariantType,
117};
118
119wrapper! {
120 #[doc(alias = "GVariant")]
125 pub struct Variant(Shared<ffi::GVariant>);
126
127 match fn {
128 ref => |ptr| ffi::g_variant_ref_sink(ptr),
129 unref => |ptr| ffi::g_variant_unref(ptr),
130 }
131}
132
133impl StaticType for Variant {
134 #[inline]
135 fn static_type() -> Type {
136 Type::VARIANT
137 }
138}
139
140#[doc(hidden)]
141impl crate::value::ValueType for Variant {
142 type Type = Variant;
143}
144
145#[doc(hidden)]
146impl crate::value::ValueTypeOptional for Variant {}
147
148#[doc(hidden)]
149unsafe impl<'a> crate::value::FromValue<'a> for Variant {
150 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
151
152 unsafe fn from_value(value: &'a crate::Value) -> Self {
153 let ptr = gobject_ffi::g_value_dup_variant(value.to_glib_none().0);
154 debug_assert!(!ptr.is_null());
155 from_glib_full(ptr)
156 }
157}
158
159#[doc(hidden)]
160impl crate::value::ToValue for Variant {
161 fn to_value(&self) -> crate::Value {
162 unsafe {
163 let mut value = crate::Value::from_type_unchecked(Variant::static_type());
164 gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, self.to_glib_full());
165 value
166 }
167 }
168
169 fn value_type(&self) -> crate::Type {
170 Variant::static_type()
171 }
172}
173
174#[doc(hidden)]
175impl From<Variant> for crate::Value {
176 #[inline]
177 fn from(v: Variant) -> Self {
178 unsafe {
179 let mut value = crate::Value::from_type_unchecked(Variant::static_type());
180 gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, v.into_glib_ptr());
181 value
182 }
183 }
184}
185
186#[doc(hidden)]
187impl crate::value::ToValueOptional for Variant {
188 fn to_value_optional(s: Option<&Self>) -> crate::Value {
189 let mut value = crate::Value::for_value_type::<Self>();
190 unsafe {
191 gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, s.to_glib_full());
192 }
193
194 value
195 }
196}
197
198#[derive(Clone, PartialEq, Eq, Debug)]
202pub struct VariantTypeMismatchError {
203 pub actual: VariantType,
204 pub expected: VariantType,
205}
206
207impl VariantTypeMismatchError {
208 pub fn new(actual: VariantType, expected: VariantType) -> Self {
209 Self { actual, expected }
210 }
211}
212
213impl fmt::Display for VariantTypeMismatchError {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 write!(
216 f,
217 "Type mismatch: Expected '{}' got '{}'",
218 self.expected, self.actual
219 )
220 }
221}
222
223impl std::error::Error for VariantTypeMismatchError {}
224
225impl Variant {
226 #[doc(alias = "g_variant_get_type")]
229 pub fn type_(&self) -> &VariantTy {
230 unsafe { VariantTy::from_ptr(ffi::g_variant_get_type(self.to_glib_none().0)) }
231 }
232
233 #[inline]
236 #[doc(alias = "g_variant_is_of_type")]
237 pub fn is<T: StaticVariantType>(&self) -> bool {
238 self.is_type(&T::static_variant_type())
239 }
240
241 #[inline]
246 #[doc(alias = "g_variant_is_of_type")]
247 pub fn is_type(&self, type_: &VariantTy) -> bool {
248 unsafe {
249 from_glib(ffi::g_variant_is_of_type(
250 self.to_glib_none().0,
251 type_.to_glib_none().0,
252 ))
253 }
254 }
255
256 #[doc(alias = "g_variant_classify")]
259 pub fn classify(&self) -> crate::VariantClass {
260 unsafe { from_glib(ffi::g_variant_classify(self.to_glib_none().0)) }
261 }
262
263 #[inline]
268 pub fn get<T: FromVariant>(&self) -> Option<T> {
269 T::from_variant(self)
270 }
271
272 pub fn try_get<T: FromVariant>(&self) -> Result<T, VariantTypeMismatchError> {
275 self.get().ok_or_else(|| {
276 VariantTypeMismatchError::new(
277 self.type_().to_owned(),
278 T::static_variant_type().into_owned(),
279 )
280 })
281 }
282
283 #[inline]
286 pub fn from_variant(value: &Variant) -> Self {
287 unsafe { from_glib_none(ffi::g_variant_new_variant(value.to_glib_none().0)) }
288 }
289
290 #[inline]
295 #[doc(alias = "get_variant")]
296 pub fn as_variant(&self) -> Option<Variant> {
297 unsafe { from_glib_full(ffi::g_variant_get_variant(self.to_glib_none().0)) }
298 }
299
300 #[doc(alias = "get_child_value")]
308 #[doc(alias = "g_variant_get_child_value")]
309 #[must_use]
310 pub fn child_value(&self, index: usize) -> Variant {
311 assert!(self.is_container());
312 assert!(index < self.n_children());
313
314 unsafe { from_glib_full(ffi::g_variant_get_child_value(self.to_glib_none().0, index)) }
315 }
316
317 pub fn try_child_value(&self, index: usize) -> Option<Variant> {
323 if !(self.is_container() && index < self.n_children()) {
324 return None;
325 }
326
327 let v =
328 unsafe { from_glib_full(ffi::g_variant_get_child_value(self.to_glib_none().0, index)) };
329 Some(v)
330 }
331
332 pub fn try_child_get<T: StaticVariantType + FromVariant>(
339 &self,
340 index: usize,
341 ) -> Result<Option<T>, VariantTypeMismatchError> {
342 self.try_child_value(index).map(|v| v.try_get()).transpose()
345 }
346
347 pub fn child_get<T: StaticVariantType + FromVariant>(&self, index: usize) -> T {
356 self.child_value(index).get().unwrap()
359 }
360
361 #[doc(alias = "get_str")]
367 #[doc(alias = "g_variant_get_string")]
368 pub fn str(&self) -> Option<&str> {
369 unsafe {
370 match self.type_().as_str() {
371 "s" | "o" | "g" => {
372 let mut len = 0;
373 let ptr = ffi::g_variant_get_string(self.to_glib_none().0, &mut len);
374 if len == 0 {
375 Some("")
376 } else {
377 let ret = str::from_utf8_unchecked(slice::from_raw_parts(
378 ptr as *const u8,
379 len as _,
380 ));
381 Some(ret)
382 }
383 }
384 _ => None,
385 }
386 }
387 }
388
389 #[doc(alias = "g_variant_get_fixed_array")]
394 pub fn fixed_array<T: FixedSizeVariantType>(&self) -> Result<&[T], VariantTypeMismatchError> {
395 unsafe {
396 let expected_ty = T::static_variant_type().as_array();
397 if self.type_() != expected_ty {
398 return Err(VariantTypeMismatchError {
399 actual: self.type_().to_owned(),
400 expected: expected_ty.into_owned(),
401 });
402 }
403
404 let mut n_elements = mem::MaybeUninit::uninit();
405 let ptr = ffi::g_variant_get_fixed_array(
406 self.to_glib_none().0,
407 n_elements.as_mut_ptr(),
408 mem::size_of::<T>(),
409 );
410
411 let n_elements = n_elements.assume_init();
412 if n_elements == 0 {
413 Ok(&[])
414 } else {
415 debug_assert!(!ptr.is_null());
416 Ok(slice::from_raw_parts(ptr as *const T, n_elements))
417 }
418 }
419 }
420
421 #[doc(alias = "g_variant_new_array")]
428 pub fn array_from_iter<T: StaticVariantType>(
429 children: impl IntoIterator<Item = Variant>,
430 ) -> Self {
431 Self::array_from_iter_with_type(&T::static_variant_type(), children)
432 }
433
434 #[doc(alias = "g_variant_new_array")]
441 pub fn array_from_iter_with_type(
442 type_: &VariantTy,
443 children: impl IntoIterator<Item = impl AsRef<Variant>>,
444 ) -> Self {
445 unsafe {
446 let mut builder = mem::MaybeUninit::uninit();
447 ffi::g_variant_builder_init(builder.as_mut_ptr(), type_.as_array().to_glib_none().0);
448 let mut builder = builder.assume_init();
449 for value in children.into_iter() {
450 let value = value.as_ref();
451 if ffi::g_variant_is_of_type(value.to_glib_none().0, type_.to_glib_none().0)
452 == ffi::GFALSE
453 {
454 ffi::g_variant_builder_clear(&mut builder);
455 assert!(value.is_type(type_));
456 }
457
458 ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
459 }
460 from_glib_none(ffi::g_variant_builder_end(&mut builder))
461 }
462 }
463
464 #[doc(alias = "g_variant_new_fixed_array")]
467 pub fn array_from_fixed_array<T: FixedSizeVariantType>(array: &[T]) -> Self {
468 let type_ = T::static_variant_type();
469
470 unsafe {
471 from_glib_none(ffi::g_variant_new_fixed_array(
472 type_.as_ptr(),
473 array.as_ptr() as ffi::gconstpointer,
474 array.len(),
475 mem::size_of::<T>(),
476 ))
477 }
478 }
479
480 #[doc(alias = "g_variant_new_tuple")]
483 pub fn tuple_from_iter(children: impl IntoIterator<Item = impl AsRef<Variant>>) -> Self {
484 unsafe {
485 let mut builder = mem::MaybeUninit::uninit();
486 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
487 let mut builder = builder.assume_init();
488 for value in children.into_iter() {
489 ffi::g_variant_builder_add_value(&mut builder, value.as_ref().to_glib_none().0);
490 }
491 from_glib_none(ffi::g_variant_builder_end(&mut builder))
492 }
493 }
494
495 #[doc(alias = "g_variant_new_dict_entry")]
500 pub fn from_dict_entry(key: &Variant, value: &Variant) -> Self {
501 unsafe {
502 from_glib_none(ffi::g_variant_new_dict_entry(
503 key.to_glib_none().0,
504 value.to_glib_none().0,
505 ))
506 }
507 }
508
509 #[doc(alias = "g_variant_new_maybe")]
512 pub fn from_maybe<T: StaticVariantType>(child: Option<&Variant>) -> Self {
513 let type_ = T::static_variant_type();
514 match child {
515 Some(child) => {
516 assert_eq!(type_, child.type_());
517
518 Self::from_some(child)
519 }
520 None => Self::from_none(&type_),
521 }
522 }
523
524 #[doc(alias = "g_variant_new_maybe")]
527 pub fn from_some(child: &Variant) -> Self {
528 unsafe {
529 from_glib_none(ffi::g_variant_new_maybe(
530 ptr::null(),
531 child.to_glib_none().0,
532 ))
533 }
534 }
535
536 #[doc(alias = "g_variant_new_maybe")]
539 pub fn from_none(type_: &VariantTy) -> Self {
540 unsafe {
541 from_glib_none(ffi::g_variant_new_maybe(
542 type_.to_glib_none().0,
543 ptr::null_mut(),
544 ))
545 }
546 }
547
548 #[inline]
557 pub fn as_maybe(&self) -> Option<Variant> {
558 assert!(self.type_().is_maybe());
559
560 unsafe { from_glib_full(ffi::g_variant_get_maybe(self.to_glib_none().0)) }
561 }
562
563 #[doc(alias = "g_variant_print")]
568 pub fn print(&self, type_annotate: bool) -> crate::GString {
569 unsafe {
570 from_glib_full(ffi::g_variant_print(
571 self.to_glib_none().0,
572 type_annotate.into_glib(),
573 ))
574 }
575 }
576
577 #[doc(alias = "g_variant_parse")]
580 pub fn parse(type_: Option<&VariantTy>, text: &str) -> Result<Self, crate::Error> {
581 unsafe {
582 let mut error = ptr::null_mut();
583 let text = text.as_bytes().as_ptr_range();
584 let variant = ffi::g_variant_parse(
585 type_.to_glib_none().0,
586 text.start as *const _,
587 text.end as *const _,
588 ptr::null_mut(),
589 &mut error,
590 );
591 if variant.is_null() {
592 debug_assert!(!error.is_null());
593 Err(from_glib_full(error))
594 } else {
595 debug_assert!(error.is_null());
596 Ok(from_glib_full(variant))
597 }
598 }
599 }
600
601 #[doc(alias = "g_variant_new_from_bytes")]
604 pub fn from_bytes<T: StaticVariantType>(bytes: &Bytes) -> Self {
605 Variant::from_bytes_with_type(bytes, &T::static_variant_type())
606 }
607
608 pub unsafe fn from_bytes_trusted<T: StaticVariantType>(bytes: &Bytes) -> Self {
622 Variant::from_bytes_with_type_trusted(bytes, &T::static_variant_type())
623 }
624
625 #[doc(alias = "g_variant_new_from_data")]
628 pub fn from_data<T: StaticVariantType, A: AsRef<[u8]>>(data: A) -> Self {
629 Variant::from_data_with_type(data, &T::static_variant_type())
630 }
631
632 pub unsafe fn from_data_trusted<T: StaticVariantType, A: AsRef<[u8]>>(data: A) -> Self {
646 Variant::from_data_with_type_trusted(data, &T::static_variant_type())
647 }
648
649 #[doc(alias = "g_variant_new_from_bytes")]
652 pub fn from_bytes_with_type(bytes: &Bytes, type_: &VariantTy) -> Self {
653 unsafe {
654 from_glib_none(ffi::g_variant_new_from_bytes(
655 type_.as_ptr() as *const _,
656 bytes.to_glib_none().0,
657 false.into_glib(),
658 ))
659 }
660 }
661
662 pub unsafe fn from_bytes_with_type_trusted(bytes: &Bytes, type_: &VariantTy) -> Self {
676 from_glib_none(ffi::g_variant_new_from_bytes(
677 type_.as_ptr() as *const _,
678 bytes.to_glib_none().0,
679 true.into_glib(),
680 ))
681 }
682
683 #[doc(alias = "g_variant_new_from_data")]
686 pub fn from_data_with_type<A: AsRef<[u8]>>(data: A, type_: &VariantTy) -> Self {
687 unsafe {
688 let data = Box::new(data);
689 let (data_ptr, len) = {
690 let data = (*data).as_ref();
691 (data.as_ptr(), data.len())
692 };
693
694 unsafe extern "C" fn free_data<A: AsRef<[u8]>>(ptr: ffi::gpointer) {
695 let _ = Box::from_raw(ptr as *mut A);
696 }
697
698 from_glib_none(ffi::g_variant_new_from_data(
699 type_.as_ptr() as *const _,
700 data_ptr as ffi::gconstpointer,
701 len,
702 false.into_glib(),
703 Some(free_data::<A>),
704 Box::into_raw(data) as ffi::gpointer,
705 ))
706 }
707 }
708
709 pub unsafe fn from_data_with_type_trusted<A: AsRef<[u8]>>(data: A, type_: &VariantTy) -> Self {
723 let data = Box::new(data);
724 let (data_ptr, len) = {
725 let data = (*data).as_ref();
726 (data.as_ptr(), data.len())
727 };
728
729 unsafe extern "C" fn free_data<A: AsRef<[u8]>>(ptr: ffi::gpointer) {
730 let _ = Box::from_raw(ptr as *mut A);
731 }
732
733 from_glib_none(ffi::g_variant_new_from_data(
734 type_.as_ptr() as *const _,
735 data_ptr as ffi::gconstpointer,
736 len,
737 true.into_glib(),
738 Some(free_data::<A>),
739 Box::into_raw(data) as ffi::gpointer,
740 ))
741 }
742
743 #[doc(alias = "get_data_as_bytes")]
746 #[doc(alias = "g_variant_get_data_as_bytes")]
747 pub fn data_as_bytes(&self) -> Bytes {
748 unsafe { from_glib_full(ffi::g_variant_get_data_as_bytes(self.to_glib_none().0)) }
749 }
750
751 #[doc(alias = "g_variant_get_data")]
754 pub fn data(&self) -> &[u8] {
755 unsafe {
756 let selfv = self.to_glib_none();
757 let len = ffi::g_variant_get_size(selfv.0);
758 if len == 0 {
759 return &[];
760 }
761 let ptr = ffi::g_variant_get_data(selfv.0);
762 slice::from_raw_parts(ptr as *const _, len as _)
763 }
764 }
765
766 #[doc(alias = "g_variant_get_size")]
769 pub fn size(&self) -> usize {
770 unsafe { ffi::g_variant_get_size(self.to_glib_none().0) }
771 }
772
773 #[doc(alias = "g_variant_store")]
778 pub fn store(&self, data: &mut [u8]) -> Result<usize, crate::BoolError> {
779 unsafe {
780 let size = ffi::g_variant_get_size(self.to_glib_none().0);
781 if data.len() < size {
782 return Err(bool_error!("Provided slice is too small"));
783 }
784
785 ffi::g_variant_store(self.to_glib_none().0, data.as_mut_ptr() as ffi::gpointer);
786
787 Ok(size)
788 }
789 }
790
791 #[doc(alias = "g_variant_get_normal_form")]
794 #[must_use]
795 pub fn normal_form(&self) -> Self {
796 unsafe { from_glib_full(ffi::g_variant_get_normal_form(self.to_glib_none().0)) }
797 }
798
799 #[doc(alias = "g_variant_byteswap")]
802 #[must_use]
803 pub fn byteswap(&self) -> Self {
804 unsafe { from_glib_full(ffi::g_variant_byteswap(self.to_glib_none().0)) }
805 }
806
807 #[doc(alias = "g_variant_n_children")]
810 pub fn n_children(&self) -> usize {
811 assert!(self.is_container());
812
813 unsafe { ffi::g_variant_n_children(self.to_glib_none().0) }
814 }
815
816 pub fn iter(&self) -> VariantIter {
822 assert!(self.is_container());
823
824 VariantIter::new(self.clone())
825 }
826
827 pub fn array_iter_str(&self) -> Result<VariantStrIter<'_>, VariantTypeMismatchError> {
846 let child_ty = String::static_variant_type();
847 let actual_ty = self.type_();
848 let expected_ty = child_ty.as_array();
849 if actual_ty != expected_ty {
850 return Err(VariantTypeMismatchError {
851 actual: actual_ty.to_owned(),
852 expected: expected_ty.into_owned(),
853 });
854 }
855
856 Ok(VariantStrIter::new(self))
857 }
858
859 #[doc(alias = "g_variant_is_container")]
862 pub fn is_container(&self) -> bool {
863 unsafe { from_glib(ffi::g_variant_is_container(self.to_glib_none().0)) }
864 }
865
866 #[doc(alias = "g_variant_is_normal_form")]
869 pub fn is_normal_form(&self) -> bool {
870 unsafe { from_glib(ffi::g_variant_is_normal_form(self.to_glib_none().0)) }
871 }
872
873 #[doc(alias = "g_variant_is_object_path")]
876 pub fn is_object_path(string: &str) -> bool {
877 unsafe { from_glib(ffi::g_variant_is_object_path(string.to_glib_none().0)) }
878 }
879
880 #[doc(alias = "g_variant_is_signature")]
883 pub fn is_signature(string: &str) -> bool {
884 unsafe { from_glib(ffi::g_variant_is_signature(string.to_glib_none().0)) }
885 }
886}
887
888unsafe impl Send for Variant {}
889unsafe impl Sync for Variant {}
890
891impl fmt::Debug for Variant {
892 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
893 f.debug_struct("Variant")
894 .field("ptr", &ToGlibPtr::<*const _>::to_glib_none(self).0)
895 .field("type", &self.type_())
896 .field("value", &self.to_string())
897 .finish()
898 }
899}
900
901impl fmt::Display for Variant {
902 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
903 f.write_str(&self.print(true))
904 }
905}
906
907impl str::FromStr for Variant {
908 type Err = crate::Error;
909
910 fn from_str(s: &str) -> Result<Self, Self::Err> {
911 Self::parse(None, s)
912 }
913}
914
915impl PartialEq for Variant {
916 #[doc(alias = "g_variant_equal")]
917 fn eq(&self, other: &Self) -> bool {
918 unsafe {
919 from_glib(ffi::g_variant_equal(
920 ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
921 ToGlibPtr::<*const _>::to_glib_none(other).0 as *const _,
922 ))
923 }
924 }
925}
926
927impl Eq for Variant {}
928
929impl PartialOrd for Variant {
930 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
931 unsafe {
932 if ffi::g_variant_classify(self.to_glib_none().0)
933 != ffi::g_variant_classify(other.to_glib_none().0)
934 {
935 return None;
936 }
937
938 if self.is_container() {
939 return None;
940 }
941
942 let res = ffi::g_variant_compare(
943 ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
944 ToGlibPtr::<*const _>::to_glib_none(other).0 as *const _,
945 );
946
947 Some(res.cmp(&0))
948 }
949 }
950}
951
952impl Hash for Variant {
953 #[doc(alias = "g_variant_hash")]
954 fn hash<H: Hasher>(&self, state: &mut H) {
955 unsafe {
956 state.write_u32(ffi::g_variant_hash(
957 ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
958 ))
959 }
960 }
961}
962
963impl AsRef<Variant> for Variant {
964 #[inline]
965 fn as_ref(&self) -> &Self {
966 self
967 }
968}
969
970pub trait ToVariant {
973 fn to_variant(&self) -> Variant;
976}
977
978pub trait FromVariant: Sized + StaticVariantType {
981 fn from_variant(variant: &Variant) -> Option<Self>;
986}
987
988pub trait StaticVariantType {
991 fn static_variant_type() -> Cow<'static, VariantTy>;
994}
995
996impl StaticVariantType for Variant {
997 fn static_variant_type() -> Cow<'static, VariantTy> {
998 Cow::Borrowed(VariantTy::VARIANT)
999 }
1000}
1001
1002impl<T: ?Sized + ToVariant> ToVariant for &T {
1003 fn to_variant(&self) -> Variant {
1004 <T as ToVariant>::to_variant(self)
1005 }
1006}
1007
1008impl<'a, T: Into<Variant> + Clone> From<&'a T> for Variant {
1009 #[inline]
1010 fn from(v: &'a T) -> Self {
1011 v.clone().into()
1012 }
1013}
1014
1015impl<T: ?Sized + StaticVariantType> StaticVariantType for &T {
1016 fn static_variant_type() -> Cow<'static, VariantTy> {
1017 <T as StaticVariantType>::static_variant_type()
1018 }
1019}
1020
1021macro_rules! impl_numeric {
1022 ($name:ty, $typ:expr, $new_fn:ident, $get_fn:ident) => {
1023 impl StaticVariantType for $name {
1024 fn static_variant_type() -> Cow<'static, VariantTy> {
1025 Cow::Borrowed($typ)
1026 }
1027 }
1028
1029 impl ToVariant for $name {
1030 fn to_variant(&self) -> Variant {
1031 unsafe { from_glib_none(ffi::$new_fn(*self)) }
1032 }
1033 }
1034
1035 impl From<$name> for Variant {
1036 #[inline]
1037 fn from(v: $name) -> Self {
1038 v.to_variant()
1039 }
1040 }
1041
1042 impl FromVariant for $name {
1043 fn from_variant(variant: &Variant) -> Option<Self> {
1044 unsafe {
1045 if variant.is::<Self>() {
1046 Some(ffi::$get_fn(variant.to_glib_none().0))
1047 } else {
1048 None
1049 }
1050 }
1051 }
1052 }
1053 };
1054}
1055
1056impl_numeric!(u8, VariantTy::BYTE, g_variant_new_byte, g_variant_get_byte);
1057impl_numeric!(
1058 i16,
1059 VariantTy::INT16,
1060 g_variant_new_int16,
1061 g_variant_get_int16
1062);
1063impl_numeric!(
1064 u16,
1065 VariantTy::UINT16,
1066 g_variant_new_uint16,
1067 g_variant_get_uint16
1068);
1069impl_numeric!(
1070 i32,
1071 VariantTy::INT32,
1072 g_variant_new_int32,
1073 g_variant_get_int32
1074);
1075impl_numeric!(
1076 u32,
1077 VariantTy::UINT32,
1078 g_variant_new_uint32,
1079 g_variant_get_uint32
1080);
1081impl_numeric!(
1082 i64,
1083 VariantTy::INT64,
1084 g_variant_new_int64,
1085 g_variant_get_int64
1086);
1087impl_numeric!(
1088 u64,
1089 VariantTy::UINT64,
1090 g_variant_new_uint64,
1091 g_variant_get_uint64
1092);
1093impl_numeric!(
1094 f64,
1095 VariantTy::DOUBLE,
1096 g_variant_new_double,
1097 g_variant_get_double
1098);
1099
1100impl StaticVariantType for () {
1101 fn static_variant_type() -> Cow<'static, VariantTy> {
1102 Cow::Borrowed(VariantTy::UNIT)
1103 }
1104}
1105
1106impl ToVariant for () {
1107 fn to_variant(&self) -> Variant {
1108 unsafe { from_glib_none(ffi::g_variant_new_tuple(ptr::null(), 0)) }
1109 }
1110}
1111
1112impl From<()> for Variant {
1113 #[inline]
1114 fn from(_: ()) -> Self {
1115 ().to_variant()
1116 }
1117}
1118
1119impl FromVariant for () {
1120 fn from_variant(variant: &Variant) -> Option<Self> {
1121 if variant.is::<Self>() {
1122 Some(())
1123 } else {
1124 None
1125 }
1126 }
1127}
1128
1129impl StaticVariantType for bool {
1130 fn static_variant_type() -> Cow<'static, VariantTy> {
1131 Cow::Borrowed(VariantTy::BOOLEAN)
1132 }
1133}
1134
1135impl ToVariant for bool {
1136 fn to_variant(&self) -> Variant {
1137 unsafe { from_glib_none(ffi::g_variant_new_boolean(self.into_glib())) }
1138 }
1139}
1140
1141impl From<bool> for Variant {
1142 #[inline]
1143 fn from(v: bool) -> Self {
1144 v.to_variant()
1145 }
1146}
1147
1148impl FromVariant for bool {
1149 fn from_variant(variant: &Variant) -> Option<Self> {
1150 unsafe {
1151 if variant.is::<Self>() {
1152 Some(from_glib(ffi::g_variant_get_boolean(
1153 variant.to_glib_none().0,
1154 )))
1155 } else {
1156 None
1157 }
1158 }
1159 }
1160}
1161
1162impl StaticVariantType for String {
1163 fn static_variant_type() -> Cow<'static, VariantTy> {
1164 Cow::Borrowed(VariantTy::STRING)
1165 }
1166}
1167
1168impl ToVariant for String {
1169 fn to_variant(&self) -> Variant {
1170 self[..].to_variant()
1171 }
1172}
1173
1174impl From<String> for Variant {
1175 #[inline]
1176 fn from(s: String) -> Self {
1177 s.to_variant()
1178 }
1179}
1180
1181impl FromVariant for String {
1182 fn from_variant(variant: &Variant) -> Option<Self> {
1183 variant.str().map(String::from)
1184 }
1185}
1186
1187impl StaticVariantType for str {
1188 fn static_variant_type() -> Cow<'static, VariantTy> {
1189 String::static_variant_type()
1190 }
1191}
1192
1193impl ToVariant for str {
1194 fn to_variant(&self) -> Variant {
1195 unsafe { from_glib_none(ffi::g_variant_new_take_string(self.to_glib_full())) }
1196 }
1197}
1198
1199impl From<&str> for Variant {
1200 #[inline]
1201 fn from(s: &str) -> Self {
1202 s.to_variant()
1203 }
1204}
1205
1206impl StaticVariantType for std::path::PathBuf {
1207 fn static_variant_type() -> Cow<'static, VariantTy> {
1208 std::path::Path::static_variant_type()
1209 }
1210}
1211
1212impl ToVariant for std::path::PathBuf {
1213 fn to_variant(&self) -> Variant {
1214 self.as_path().to_variant()
1215 }
1216}
1217
1218impl From<std::path::PathBuf> for Variant {
1219 #[inline]
1220 fn from(p: std::path::PathBuf) -> Self {
1221 p.to_variant()
1222 }
1223}
1224
1225impl FromVariant for std::path::PathBuf {
1226 fn from_variant(variant: &Variant) -> Option<Self> {
1227 unsafe {
1228 let ptr = ffi::g_variant_get_bytestring(variant.to_glib_none().0);
1229 Some(crate::translate::c_to_path_buf(ptr as *const _))
1230 }
1231 }
1232}
1233
1234impl StaticVariantType for std::path::Path {
1235 fn static_variant_type() -> Cow<'static, VariantTy> {
1236 <&[u8]>::static_variant_type()
1237 }
1238}
1239
1240impl ToVariant for std::path::Path {
1241 fn to_variant(&self) -> Variant {
1242 let tmp = crate::translate::path_to_c(self);
1243 unsafe { from_glib_none(ffi::g_variant_new_bytestring(tmp.as_ptr() as *const u8)) }
1244 }
1245}
1246
1247impl From<&std::path::Path> for Variant {
1248 #[inline]
1249 fn from(p: &std::path::Path) -> Self {
1250 p.to_variant()
1251 }
1252}
1253
1254impl StaticVariantType for std::ffi::OsString {
1255 fn static_variant_type() -> Cow<'static, VariantTy> {
1256 std::ffi::OsStr::static_variant_type()
1257 }
1258}
1259
1260impl ToVariant for std::ffi::OsString {
1261 fn to_variant(&self) -> Variant {
1262 self.as_os_str().to_variant()
1263 }
1264}
1265
1266impl From<std::ffi::OsString> for Variant {
1267 #[inline]
1268 fn from(s: std::ffi::OsString) -> Self {
1269 s.to_variant()
1270 }
1271}
1272
1273impl FromVariant for std::ffi::OsString {
1274 fn from_variant(variant: &Variant) -> Option<Self> {
1275 unsafe {
1276 let ptr = ffi::g_variant_get_bytestring(variant.to_glib_none().0);
1277 Some(crate::translate::c_to_os_string(ptr as *const _))
1278 }
1279 }
1280}
1281
1282impl StaticVariantType for std::ffi::OsStr {
1283 fn static_variant_type() -> Cow<'static, VariantTy> {
1284 <&[u8]>::static_variant_type()
1285 }
1286}
1287
1288impl ToVariant for std::ffi::OsStr {
1289 fn to_variant(&self) -> Variant {
1290 let tmp = crate::translate::os_str_to_c(self);
1291 unsafe { from_glib_none(ffi::g_variant_new_bytestring(tmp.as_ptr() as *const u8)) }
1292 }
1293}
1294
1295impl From<&std::ffi::OsStr> for Variant {
1296 #[inline]
1297 fn from(s: &std::ffi::OsStr) -> Self {
1298 s.to_variant()
1299 }
1300}
1301
1302impl<T: StaticVariantType> StaticVariantType for Option<T> {
1303 fn static_variant_type() -> Cow<'static, VariantTy> {
1304 Cow::Owned(VariantType::new_maybe(&T::static_variant_type()))
1305 }
1306}
1307
1308impl<T: StaticVariantType + ToVariant> ToVariant for Option<T> {
1309 fn to_variant(&self) -> Variant {
1310 Variant::from_maybe::<T>(self.as_ref().map(|m| m.to_variant()).as_ref())
1311 }
1312}
1313
1314impl<T: StaticVariantType + Into<Variant>> From<Option<T>> for Variant {
1315 #[inline]
1316 fn from(v: Option<T>) -> Self {
1317 Variant::from_maybe::<T>(v.map(|v| v.into()).as_ref())
1318 }
1319}
1320
1321impl<T: StaticVariantType + FromVariant> FromVariant for Option<T> {
1322 fn from_variant(variant: &Variant) -> Option<Self> {
1323 unsafe {
1324 if variant.is::<Self>() {
1325 let c_child = ffi::g_variant_get_maybe(variant.to_glib_none().0);
1326 if !c_child.is_null() {
1327 let child: Variant = from_glib_full(c_child);
1328
1329 Some(T::from_variant(&child))
1330 } else {
1331 Some(None)
1332 }
1333 } else {
1334 None
1335 }
1336 }
1337 }
1338}
1339
1340impl<T: StaticVariantType> StaticVariantType for [T] {
1341 fn static_variant_type() -> Cow<'static, VariantTy> {
1342 T::static_variant_type().as_array()
1343 }
1344}
1345
1346impl<T: StaticVariantType + ToVariant> ToVariant for [T] {
1347 fn to_variant(&self) -> Variant {
1348 unsafe {
1349 if self.is_empty() {
1350 return from_glib_none(ffi::g_variant_new_array(
1351 T::static_variant_type().to_glib_none().0,
1352 ptr::null(),
1353 0,
1354 ));
1355 }
1356
1357 let mut builder = mem::MaybeUninit::uninit();
1358 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1359 let mut builder = builder.assume_init();
1360 for value in self {
1361 let value = value.to_variant();
1362 ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
1363 }
1364 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1365 }
1366 }
1367}
1368
1369impl<T: StaticVariantType + ToVariant> From<&[T]> for Variant {
1370 #[inline]
1371 fn from(s: &[T]) -> Self {
1372 s.to_variant()
1373 }
1374}
1375
1376impl<T: FromVariant> FromVariant for Vec<T> {
1377 fn from_variant(variant: &Variant) -> Option<Self> {
1378 if !variant.is_container() {
1379 return None;
1380 }
1381
1382 let mut vec = Vec::with_capacity(variant.n_children());
1383
1384 for i in 0..variant.n_children() {
1385 match variant.child_value(i).get() {
1386 Some(child) => vec.push(child),
1387 None => return None,
1388 }
1389 }
1390
1391 Some(vec)
1392 }
1393}
1394
1395impl<T: StaticVariantType + ToVariant> ToVariant for Vec<T> {
1396 fn to_variant(&self) -> Variant {
1397 self.as_slice().to_variant()
1398 }
1399}
1400
1401impl<T: StaticVariantType + Into<Variant>> From<Vec<T>> for Variant {
1402 fn from(v: Vec<T>) -> Self {
1403 unsafe {
1404 if v.is_empty() {
1405 return from_glib_none(ffi::g_variant_new_array(
1406 T::static_variant_type().to_glib_none().0,
1407 ptr::null(),
1408 0,
1409 ));
1410 }
1411
1412 let mut builder = mem::MaybeUninit::uninit();
1413 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1414 let mut builder = builder.assume_init();
1415 for value in v {
1416 let value = value.into();
1417 ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
1418 }
1419 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1420 }
1421 }
1422}
1423
1424impl<T: StaticVariantType> StaticVariantType for Vec<T> {
1425 fn static_variant_type() -> Cow<'static, VariantTy> {
1426 <[T]>::static_variant_type()
1427 }
1428}
1429
1430impl<K, V, H> FromVariant for HashMap<K, V, H>
1431where
1432 K: FromVariant + Eq + Hash,
1433 V: FromVariant,
1434 H: BuildHasher + Default,
1435{
1436 fn from_variant(variant: &Variant) -> Option<Self> {
1437 if !variant.is_container() {
1438 return None;
1439 }
1440
1441 let mut map = HashMap::default();
1442
1443 for i in 0..variant.n_children() {
1444 let entry = variant.child_value(i);
1445 let key = entry.child_value(0).get()?;
1446 let val = entry.child_value(1).get()?;
1447
1448 map.insert(key, val);
1449 }
1450
1451 Some(map)
1452 }
1453}
1454
1455impl<K, V> FromVariant for BTreeMap<K, V>
1456where
1457 K: FromVariant + Eq + Ord,
1458 V: FromVariant,
1459{
1460 fn from_variant(variant: &Variant) -> Option<Self> {
1461 if !variant.is_container() {
1462 return None;
1463 }
1464
1465 let mut map = BTreeMap::default();
1466
1467 for i in 0..variant.n_children() {
1468 let entry = variant.child_value(i);
1469 let key = entry.child_value(0).get()?;
1470 let val = entry.child_value(1).get()?;
1471
1472 map.insert(key, val);
1473 }
1474
1475 Some(map)
1476 }
1477}
1478
1479impl<K, V> ToVariant for HashMap<K, V>
1480where
1481 K: StaticVariantType + ToVariant + Eq + Hash,
1482 V: StaticVariantType + ToVariant,
1483{
1484 fn to_variant(&self) -> Variant {
1485 unsafe {
1486 if self.is_empty() {
1487 return from_glib_none(ffi::g_variant_new_array(
1488 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
1489 ptr::null(),
1490 0,
1491 ));
1492 }
1493
1494 let mut builder = mem::MaybeUninit::uninit();
1495 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1496 let mut builder = builder.assume_init();
1497 for (key, value) in self {
1498 let entry = DictEntry::new(key, value).to_variant();
1499 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
1500 }
1501 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1502 }
1503 }
1504}
1505
1506impl<K, V> From<HashMap<K, V>> for Variant
1507where
1508 K: StaticVariantType + Into<Variant> + Eq + Hash,
1509 V: StaticVariantType + Into<Variant>,
1510{
1511 fn from(m: HashMap<K, V>) -> Self {
1512 unsafe {
1513 if m.is_empty() {
1514 return from_glib_none(ffi::g_variant_new_array(
1515 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
1516 ptr::null(),
1517 0,
1518 ));
1519 }
1520
1521 let mut builder = mem::MaybeUninit::uninit();
1522 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1523 let mut builder = builder.assume_init();
1524 for (key, value) in m {
1525 let entry = Variant::from(DictEntry::new(key, value));
1526 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
1527 }
1528 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1529 }
1530 }
1531}
1532
1533impl<K, V> ToVariant for BTreeMap<K, V>
1534where
1535 K: StaticVariantType + ToVariant + Eq + Hash,
1536 V: StaticVariantType + ToVariant,
1537{
1538 fn to_variant(&self) -> Variant {
1539 unsafe {
1540 if self.is_empty() {
1541 return from_glib_none(ffi::g_variant_new_array(
1542 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
1543 ptr::null(),
1544 0,
1545 ));
1546 }
1547
1548 let mut builder = mem::MaybeUninit::uninit();
1549 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1550 let mut builder = builder.assume_init();
1551 for (key, value) in self {
1552 let entry = DictEntry::new(key, value).to_variant();
1553 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
1554 }
1555 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1556 }
1557 }
1558}
1559
1560impl<K, V> From<BTreeMap<K, V>> for Variant
1561where
1562 K: StaticVariantType + Into<Variant> + Eq + Hash,
1563 V: StaticVariantType + Into<Variant>,
1564{
1565 fn from(m: BTreeMap<K, V>) -> Self {
1566 unsafe {
1567 if m.is_empty() {
1568 return from_glib_none(ffi::g_variant_new_array(
1569 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
1570 ptr::null(),
1571 0,
1572 ));
1573 }
1574
1575 let mut builder = mem::MaybeUninit::uninit();
1576 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1577 let mut builder = builder.assume_init();
1578 for (key, value) in m {
1579 let entry = Variant::from(DictEntry::new(key, value));
1580 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
1581 }
1582 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1583 }
1584 }
1585}
1586
1587#[derive(Debug, Clone)]
1606pub struct DictEntry<K, V> {
1607 key: K,
1608 value: V,
1609}
1610
1611impl<K, V> DictEntry<K, V>
1612where
1613 K: StaticVariantType,
1614 V: StaticVariantType,
1615{
1616 pub fn new(key: K, value: V) -> Self {
1617 Self { key, value }
1618 }
1619
1620 pub fn key(&self) -> &K {
1621 &self.key
1622 }
1623
1624 pub fn value(&self) -> &V {
1625 &self.value
1626 }
1627}
1628
1629impl<K, V> FromVariant for DictEntry<K, V>
1630where
1631 K: FromVariant,
1632 V: FromVariant,
1633{
1634 fn from_variant(variant: &Variant) -> Option<Self> {
1635 if !variant.type_().is_subtype_of(VariantTy::DICT_ENTRY) {
1636 return None;
1637 }
1638
1639 let key = variant.child_value(0).get()?;
1640 let value = variant.child_value(1).get()?;
1641
1642 Some(Self { key, value })
1643 }
1644}
1645
1646impl<K, V> ToVariant for DictEntry<K, V>
1647where
1648 K: StaticVariantType + ToVariant,
1649 V: StaticVariantType + ToVariant,
1650{
1651 fn to_variant(&self) -> Variant {
1652 Variant::from_dict_entry(&self.key.to_variant(), &self.value.to_variant())
1653 }
1654}
1655
1656impl<K, V> From<DictEntry<K, V>> for Variant
1657where
1658 K: StaticVariantType + Into<Variant>,
1659 V: StaticVariantType + Into<Variant>,
1660{
1661 fn from(e: DictEntry<K, V>) -> Self {
1662 Variant::from_dict_entry(&e.key.into(), &e.value.into())
1663 }
1664}
1665
1666impl ToVariant for Variant {
1667 fn to_variant(&self) -> Variant {
1668 Variant::from_variant(self)
1669 }
1670}
1671
1672impl FromVariant for Variant {
1673 fn from_variant(variant: &Variant) -> Option<Self> {
1674 variant.as_variant()
1675 }
1676}
1677
1678impl<K: StaticVariantType, V: StaticVariantType> StaticVariantType for DictEntry<K, V> {
1679 fn static_variant_type() -> Cow<'static, VariantTy> {
1680 Cow::Owned(VariantType::new_dict_entry(
1681 &K::static_variant_type(),
1682 &V::static_variant_type(),
1683 ))
1684 }
1685}
1686
1687fn static_variant_mapping<K, V>() -> Cow<'static, VariantTy>
1688where
1689 K: StaticVariantType,
1690 V: StaticVariantType,
1691{
1692 use std::fmt::Write;
1693
1694 let key_type = K::static_variant_type();
1695 let value_type = V::static_variant_type();
1696
1697 if key_type == VariantTy::STRING && value_type == VariantTy::VARIANT {
1698 return Cow::Borrowed(VariantTy::VARDICT);
1699 }
1700
1701 let mut builder = crate::GStringBuilder::default();
1702 write!(builder, "a{{{}{}}}", key_type.as_str(), value_type.as_str()).unwrap();
1703
1704 Cow::Owned(VariantType::from_string(builder.into_string()).unwrap())
1705}
1706
1707impl<K, V, H> StaticVariantType for HashMap<K, V, H>
1708where
1709 K: StaticVariantType,
1710 V: StaticVariantType,
1711 H: BuildHasher + Default,
1712{
1713 fn static_variant_type() -> Cow<'static, VariantTy> {
1714 static_variant_mapping::<K, V>()
1715 }
1716}
1717
1718impl<K, V> StaticVariantType for BTreeMap<K, V>
1719where
1720 K: StaticVariantType,
1721 V: StaticVariantType,
1722{
1723 fn static_variant_type() -> Cow<'static, VariantTy> {
1724 static_variant_mapping::<K, V>()
1725 }
1726}
1727
1728macro_rules! tuple_impls {
1729 ($($len:expr => ($($n:tt $name:ident)+))+) => {
1730 $(
1731 impl<$($name),+> StaticVariantType for ($($name,)+)
1732 where
1733 $($name: StaticVariantType,)+
1734 {
1735 fn static_variant_type() -> Cow<'static, VariantTy> {
1736 Cow::Owned(VariantType::new_tuple(&[
1737 $(
1738 $name::static_variant_type(),
1739 )+
1740 ]))
1741 }
1742 }
1743
1744 impl<$($name),+> FromVariant for ($($name,)+)
1745 where
1746 $($name: FromVariant,)+
1747 {
1748 fn from_variant(variant: &Variant) -> Option<Self> {
1749 if !variant.type_().is_subtype_of(VariantTy::TUPLE) {
1750 return None;
1751 }
1752
1753 Some((
1754 $(
1755 match variant.try_child_get::<$name>($n) {
1756 Ok(Some(field)) => field,
1757 _ => return None,
1758 },
1759 )+
1760 ))
1761 }
1762 }
1763
1764 impl<$($name),+> ToVariant for ($($name,)+)
1765 where
1766 $($name: ToVariant,)+
1767 {
1768 fn to_variant(&self) -> Variant {
1769 unsafe {
1770 let mut builder = mem::MaybeUninit::uninit();
1771 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
1772 let mut builder = builder.assume_init();
1773
1774 $(
1775 let field = self.$n.to_variant();
1776 ffi::g_variant_builder_add_value(&mut builder, field.to_glib_none().0);
1777 )+
1778
1779 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1780 }
1781 }
1782 }
1783
1784 impl<$($name),+> From<($($name,)+)> for Variant
1785 where
1786 $($name: Into<Variant>,)+
1787 {
1788 fn from(t: ($($name,)+)) -> Self {
1789 unsafe {
1790 let mut builder = mem::MaybeUninit::uninit();
1791 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
1792 let mut builder = builder.assume_init();
1793
1794 $(
1795 let field = t.$n.into();
1796 ffi::g_variant_builder_add_value(&mut builder, field.to_glib_none().0);
1797 )+
1798
1799 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1800 }
1801 }
1802 }
1803 )+
1804 }
1805}
1806
1807tuple_impls! {
1808 1 => (0 T0)
1809 2 => (0 T0 1 T1)
1810 3 => (0 T0 1 T1 2 T2)
1811 4 => (0 T0 1 T1 2 T2 3 T3)
1812 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
1813 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
1814 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
1815 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
1816 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
1817 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
1818 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
1819 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
1820 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
1821 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
1822 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
1823 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
1824}
1825
1826impl<T: Into<Variant> + StaticVariantType> FromIterator<T> for Variant {
1827 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1828 Variant::array_from_iter::<T>(iter.into_iter().map(|v| v.into()))
1829 }
1830}
1831
1832pub unsafe trait FixedSizeVariantType: StaticVariantType + Sized + Copy {}
1834unsafe impl FixedSizeVariantType for u8 {}
1835unsafe impl FixedSizeVariantType for i16 {}
1836unsafe impl FixedSizeVariantType for u16 {}
1837unsafe impl FixedSizeVariantType for i32 {}
1838unsafe impl FixedSizeVariantType for u32 {}
1839unsafe impl FixedSizeVariantType for i64 {}
1840unsafe impl FixedSizeVariantType for u64 {}
1841unsafe impl FixedSizeVariantType for f64 {}
1842unsafe impl FixedSizeVariantType for bool {}
1843
1844#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1852pub struct FixedSizeVariantArray<A, T>(A, std::marker::PhantomData<T>)
1853where
1854 A: AsRef<[T]>,
1855 T: FixedSizeVariantType;
1856
1857impl<A: AsRef<[T]>, T: FixedSizeVariantType> From<A> for FixedSizeVariantArray<A, T> {
1858 fn from(array: A) -> Self {
1859 FixedSizeVariantArray(array, std::marker::PhantomData)
1860 }
1861}
1862
1863impl<A: AsRef<[T]>, T: FixedSizeVariantType> FixedSizeVariantArray<A, T> {
1864 pub fn into_inner(self) -> A {
1865 self.0
1866 }
1867}
1868
1869impl<A: AsRef<[T]>, T: FixedSizeVariantType> std::ops::Deref for FixedSizeVariantArray<A, T> {
1870 type Target = A;
1871
1872 #[inline]
1873 fn deref(&self) -> &Self::Target {
1874 &self.0
1875 }
1876}
1877
1878impl<A: AsRef<[T]>, T: FixedSizeVariantType> std::ops::DerefMut for FixedSizeVariantArray<A, T> {
1879 #[inline]
1880 fn deref_mut(&mut self) -> &mut Self::Target {
1881 &mut self.0
1882 }
1883}
1884
1885impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsRef<A> for FixedSizeVariantArray<A, T> {
1886 #[inline]
1887 fn as_ref(&self) -> &A {
1888 &self.0
1889 }
1890}
1891
1892impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsMut<A> for FixedSizeVariantArray<A, T> {
1893 #[inline]
1894 fn as_mut(&mut self) -> &mut A {
1895 &mut self.0
1896 }
1897}
1898
1899impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsRef<[T]> for FixedSizeVariantArray<A, T> {
1900 #[inline]
1901 fn as_ref(&self) -> &[T] {
1902 self.0.as_ref()
1903 }
1904}
1905
1906impl<A: AsRef<[T]> + AsMut<[T]>, T: FixedSizeVariantType> AsMut<[T]>
1907 for FixedSizeVariantArray<A, T>
1908{
1909 #[inline]
1910 fn as_mut(&mut self) -> &mut [T] {
1911 self.0.as_mut()
1912 }
1913}
1914
1915impl<A: AsRef<[T]>, T: FixedSizeVariantType> StaticVariantType for FixedSizeVariantArray<A, T> {
1916 fn static_variant_type() -> Cow<'static, VariantTy> {
1917 <[T]>::static_variant_type()
1918 }
1919}
1920
1921impl<A: AsRef<[T]> + for<'a> From<&'a [T]>, T: FixedSizeVariantType> FromVariant
1922 for FixedSizeVariantArray<A, T>
1923{
1924 fn from_variant(variant: &Variant) -> Option<Self> {
1925 Some(FixedSizeVariantArray(
1926 A::from(variant.fixed_array::<T>().ok()?),
1927 std::marker::PhantomData,
1928 ))
1929 }
1930}
1931
1932impl<A: AsRef<[T]>, T: FixedSizeVariantType> ToVariant for FixedSizeVariantArray<A, T> {
1933 fn to_variant(&self) -> Variant {
1934 Variant::array_from_fixed_array(self.0.as_ref())
1935 }
1936}
1937
1938impl<A: AsRef<[T]>, T: FixedSizeVariantType> From<FixedSizeVariantArray<A, T>> for Variant {
1939 #[doc(alias = "g_variant_new_from_data")]
1940 fn from(a: FixedSizeVariantArray<A, T>) -> Self {
1941 unsafe {
1942 let data = Box::new(a.0);
1943 let (data_ptr, len) = {
1944 let data = (*data).as_ref();
1945 (data.as_ptr(), mem::size_of_val(data))
1946 };
1947
1948 unsafe extern "C" fn free_data<A: AsRef<[T]>, T: FixedSizeVariantType>(
1949 ptr: ffi::gpointer,
1950 ) {
1951 let _ = Box::from_raw(ptr as *mut A);
1952 }
1953
1954 from_glib_none(ffi::g_variant_new_from_data(
1955 T::static_variant_type().to_glib_none().0,
1956 data_ptr as ffi::gconstpointer,
1957 len,
1958 false.into_glib(),
1959 Some(free_data::<A, T>),
1960 Box::into_raw(data) as ffi::gpointer,
1961 ))
1962 }
1963 }
1964}
1965
1966#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1968pub struct Handle(pub i32);
1969
1970impl From<i32> for Handle {
1971 fn from(v: i32) -> Self {
1972 Handle(v)
1973 }
1974}
1975
1976impl From<Handle> for i32 {
1977 fn from(v: Handle) -> Self {
1978 v.0
1979 }
1980}
1981
1982impl StaticVariantType for Handle {
1983 fn static_variant_type() -> Cow<'static, VariantTy> {
1984 Cow::Borrowed(VariantTy::HANDLE)
1985 }
1986}
1987
1988impl ToVariant for Handle {
1989 fn to_variant(&self) -> Variant {
1990 unsafe { from_glib_none(ffi::g_variant_new_handle(self.0)) }
1991 }
1992}
1993
1994impl From<Handle> for Variant {
1995 #[inline]
1996 fn from(h: Handle) -> Self {
1997 h.to_variant()
1998 }
1999}
2000
2001impl FromVariant for Handle {
2002 fn from_variant(variant: &Variant) -> Option<Self> {
2003 unsafe {
2004 if variant.is::<Self>() {
2005 Some(Handle(ffi::g_variant_get_handle(variant.to_glib_none().0)))
2006 } else {
2007 None
2008 }
2009 }
2010 }
2011}
2012
2013#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2017pub struct ObjectPath(String);
2018
2019impl ObjectPath {
2020 pub fn as_str(&self) -> &str {
2021 &self.0
2022 }
2023}
2024
2025impl Display for ObjectPath {
2026 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2027 self.0.fmt(f)
2028 }
2029}
2030
2031impl std::ops::Deref for ObjectPath {
2032 type Target = str;
2033
2034 #[inline]
2035 fn deref(&self) -> &Self::Target {
2036 &self.0
2037 }
2038}
2039
2040impl TryFrom<String> for ObjectPath {
2041 type Error = crate::BoolError;
2042
2043 fn try_from(v: String) -> Result<Self, Self::Error> {
2044 if !Variant::is_object_path(&v) {
2045 return Err(bool_error!("Invalid object path"));
2046 }
2047
2048 Ok(ObjectPath(v))
2049 }
2050}
2051
2052impl<'a> TryFrom<&'a str> for ObjectPath {
2053 type Error = crate::BoolError;
2054
2055 fn try_from(v: &'a str) -> Result<Self, Self::Error> {
2056 ObjectPath::try_from(String::from(v))
2057 }
2058}
2059
2060impl From<ObjectPath> for String {
2061 fn from(v: ObjectPath) -> Self {
2062 v.0
2063 }
2064}
2065
2066impl StaticVariantType for ObjectPath {
2067 fn static_variant_type() -> Cow<'static, VariantTy> {
2068 Cow::Borrowed(VariantTy::OBJECT_PATH)
2069 }
2070}
2071
2072impl ToVariant for ObjectPath {
2073 fn to_variant(&self) -> Variant {
2074 unsafe { from_glib_none(ffi::g_variant_new_object_path(self.0.to_glib_none().0)) }
2075 }
2076}
2077
2078impl From<ObjectPath> for Variant {
2079 #[inline]
2080 fn from(p: ObjectPath) -> Self {
2081 let mut s = p.0;
2082 s.push('\0');
2083 unsafe { Self::from_data_trusted::<ObjectPath, _>(s) }
2084 }
2085}
2086
2087impl FromVariant for ObjectPath {
2088 #[allow(unused_unsafe)]
2089 fn from_variant(variant: &Variant) -> Option<Self> {
2090 unsafe {
2091 if variant.is::<Self>() {
2092 Some(ObjectPath(String::from(variant.str().unwrap())))
2093 } else {
2094 None
2095 }
2096 }
2097 }
2098}
2099
2100#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2104pub struct Signature(String);
2105
2106impl Signature {
2107 pub fn as_str(&self) -> &str {
2108 &self.0
2109 }
2110}
2111
2112impl std::ops::Deref for Signature {
2113 type Target = str;
2114
2115 #[inline]
2116 fn deref(&self) -> &Self::Target {
2117 &self.0
2118 }
2119}
2120
2121impl TryFrom<String> for Signature {
2122 type Error = crate::BoolError;
2123
2124 fn try_from(v: String) -> Result<Self, Self::Error> {
2125 if !Variant::is_signature(&v) {
2126 return Err(bool_error!("Invalid signature"));
2127 }
2128
2129 Ok(Signature(v))
2130 }
2131}
2132
2133impl<'a> TryFrom<&'a str> for Signature {
2134 type Error = crate::BoolError;
2135
2136 fn try_from(v: &'a str) -> Result<Self, Self::Error> {
2137 Signature::try_from(String::from(v))
2138 }
2139}
2140
2141impl From<Signature> for String {
2142 fn from(v: Signature) -> Self {
2143 v.0
2144 }
2145}
2146
2147impl StaticVariantType for Signature {
2148 fn static_variant_type() -> Cow<'static, VariantTy> {
2149 Cow::Borrowed(VariantTy::SIGNATURE)
2150 }
2151}
2152
2153impl ToVariant for Signature {
2154 fn to_variant(&self) -> Variant {
2155 unsafe { from_glib_none(ffi::g_variant_new_signature(self.0.to_glib_none().0)) }
2156 }
2157}
2158
2159impl From<Signature> for Variant {
2160 #[inline]
2161 fn from(s: Signature) -> Self {
2162 let mut s = s.0;
2163 s.push('\0');
2164 unsafe { Self::from_data_trusted::<Signature, _>(s) }
2165 }
2166}
2167
2168impl FromVariant for Signature {
2169 #[allow(unused_unsafe)]
2170 fn from_variant(variant: &Variant) -> Option<Self> {
2171 unsafe {
2172 if variant.is::<Self>() {
2173 Some(Signature(String::from(variant.str().unwrap())))
2174 } else {
2175 None
2176 }
2177 }
2178 }
2179}
2180
2181#[cfg(test)]
2182mod tests {
2183 use std::collections::{HashMap, HashSet};
2184
2185 use super::*;
2186
2187 macro_rules! unsigned {
2188 ($name:ident, $ty:ident) => {
2189 #[test]
2190 fn $name() {
2191 let mut n = $ty::MAX;
2192 while n > 0 {
2193 let v = n.to_variant();
2194 assert_eq!(v.get(), Some(n));
2195 n /= 2;
2196 }
2197 }
2198 };
2199 }
2200
2201 macro_rules! signed {
2202 ($name:ident, $ty:ident) => {
2203 #[test]
2204 fn $name() {
2205 let mut n = $ty::MAX;
2206 while n > 0 {
2207 let v = n.to_variant();
2208 assert_eq!(v.get(), Some(n));
2209 let v = (-n).to_variant();
2210 assert_eq!(v.get(), Some(-n));
2211 n /= 2;
2212 }
2213 }
2214 };
2215 }
2216
2217 unsigned!(test_u8, u8);
2218 unsigned!(test_u16, u16);
2219 unsigned!(test_u32, u32);
2220 unsigned!(test_u64, u64);
2221 signed!(test_i16, i16);
2222 signed!(test_i32, i32);
2223 signed!(test_i64, i64);
2224
2225 #[test]
2226 fn test_str() {
2227 let s = "this is a test";
2228 let v = s.to_variant();
2229 assert_eq!(v.str(), Some(s));
2230 assert_eq!(42u32.to_variant().str(), None);
2231 }
2232
2233 #[test]
2234 fn test_fixed_array() {
2235 let b = b"this is a test";
2236 let v = Variant::array_from_fixed_array(&b[..]);
2237 assert_eq!(v.type_().as_str(), "ay");
2238 assert_eq!(v.fixed_array::<u8>().unwrap(), b);
2239 assert!(42u32.to_variant().fixed_array::<u8>().is_err());
2240
2241 let b = [1u32, 10u32, 100u32];
2242 let v = Variant::array_from_fixed_array(&b);
2243 assert_eq!(v.type_().as_str(), "au");
2244 assert_eq!(v.fixed_array::<u32>().unwrap(), b);
2245 assert!(v.fixed_array::<u8>().is_err());
2246
2247 let b = [true, false, true];
2248 let v = Variant::array_from_fixed_array(&b);
2249 assert_eq!(v.type_().as_str(), "ab");
2250 assert_eq!(v.fixed_array::<bool>().unwrap(), b);
2251 assert!(v.fixed_array::<u8>().is_err());
2252
2253 let b = [1.0f64, 2.0f64, 3.0f64];
2254 let v = Variant::array_from_fixed_array(&b);
2255 assert_eq!(v.type_().as_str(), "ad");
2256 #[allow(clippy::float_cmp)]
2257 {
2258 assert_eq!(v.fixed_array::<f64>().unwrap(), b);
2259 }
2260 assert!(v.fixed_array::<u64>().is_err());
2261 }
2262
2263 #[test]
2264 fn test_fixed_variant_array() {
2265 let b = FixedSizeVariantArray::from(&b"this is a test"[..]);
2266 let v = b.to_variant();
2267 assert_eq!(v.type_().as_str(), "ay");
2268 assert_eq!(
2269 &*v.get::<FixedSizeVariantArray<Vec<u8>, u8>>().unwrap(),
2270 &*b
2271 );
2272
2273 let b = FixedSizeVariantArray::from(vec![1i32, 2, 3]);
2274 let v = b.to_variant();
2275 assert_eq!(v.type_().as_str(), "ai");
2276 assert_eq!(v.get::<FixedSizeVariantArray<Vec<i32>, i32>>().unwrap(), b);
2277 }
2278
2279 #[test]
2280 fn test_string() {
2281 let s = String::from("this is a test");
2282 let v = s.to_variant();
2283 assert_eq!(v.get(), Some(s));
2284 assert_eq!(v.normal_form(), v);
2285 }
2286
2287 #[test]
2288 fn test_eq() {
2289 let v1 = "this is a test".to_variant();
2290 let v2 = "this is a test".to_variant();
2291 let v3 = "test".to_variant();
2292 assert_eq!(v1, v2);
2293 assert_ne!(v1, v3);
2294 }
2295
2296 #[test]
2297 fn test_hash() {
2298 let v1 = "this is a test".to_variant();
2299 let v2 = "this is a test".to_variant();
2300 let v3 = "test".to_variant();
2301 let mut set = HashSet::new();
2302 set.insert(v1);
2303 assert!(set.contains(&v2));
2304 assert!(!set.contains(&v3));
2305
2306 assert_eq!(
2307 <HashMap<&str, (&str, u8, u32)>>::static_variant_type().as_str(),
2308 "a{s(syu)}"
2309 );
2310 }
2311
2312 #[test]
2313 fn test_array() {
2314 assert_eq!(<Vec<&str>>::static_variant_type().as_str(), "as");
2315 assert_eq!(
2316 <Vec<(&str, u8, u32)>>::static_variant_type().as_str(),
2317 "a(syu)"
2318 );
2319 let a = ["foo", "bar", "baz"].to_variant();
2320 assert_eq!(a.normal_form(), a);
2321 assert_eq!(a.array_iter_str().unwrap().len(), 3);
2322 let o = 0u32.to_variant();
2323 assert!(o.array_iter_str().is_err());
2324 }
2325
2326 #[test]
2327 fn test_array_from_iter() {
2328 let a = Variant::array_from_iter::<String>(
2329 ["foo", "bar", "baz"].into_iter().map(|s| s.to_variant()),
2330 );
2331 assert_eq!(a.type_().as_str(), "as");
2332 assert_eq!(a.n_children(), 3);
2333
2334 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
2335 assert_eq!(a.try_child_get::<String>(1), Ok(Some(String::from("bar"))));
2336 assert_eq!(a.try_child_get::<String>(2), Ok(Some(String::from("baz"))));
2337 }
2338
2339 #[test]
2340 fn test_array_collect() {
2341 let a = ["foo", "bar", "baz"].into_iter().collect::<Variant>();
2342 assert_eq!(a.type_().as_str(), "as");
2343 assert_eq!(a.n_children(), 3);
2344
2345 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
2346 assert_eq!(a.try_child_get::<String>(1), Ok(Some(String::from("bar"))));
2347 assert_eq!(a.try_child_get::<String>(2), Ok(Some(String::from("baz"))));
2348 }
2349
2350 #[test]
2351 fn test_tuple() {
2352 assert_eq!(<(&str, u32)>::static_variant_type().as_str(), "(su)");
2353 assert_eq!(<(&str, u8, u32)>::static_variant_type().as_str(), "(syu)");
2354 let a = ("test", 1u8, 2u32).to_variant();
2355 assert_eq!(a.normal_form(), a);
2356 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("test"))));
2357 assert_eq!(a.try_child_get::<u8>(1), Ok(Some(1u8)));
2358 assert_eq!(a.try_child_get::<u32>(2), Ok(Some(2u32)));
2359 assert_eq!(
2360 a.try_get::<(String, u8, u32)>(),
2361 Ok((String::from("test"), 1u8, 2u32))
2362 );
2363 }
2364
2365 #[test]
2366 fn test_tuple_from_iter() {
2367 let a = Variant::tuple_from_iter(["foo".to_variant(), 1u8.to_variant(), 2i32.to_variant()]);
2368 assert_eq!(a.type_().as_str(), "(syi)");
2369 assert_eq!(a.n_children(), 3);
2370
2371 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
2372 assert_eq!(a.try_child_get::<u8>(1), Ok(Some(1u8)));
2373 assert_eq!(a.try_child_get::<i32>(2), Ok(Some(2i32)));
2374 }
2375
2376 #[test]
2377 fn test_empty() {
2378 assert_eq!(<()>::static_variant_type().as_str(), "()");
2379 let a = ().to_variant();
2380 assert_eq!(a.type_().as_str(), "()");
2381 assert_eq!(a.get::<()>(), Some(()));
2382 }
2383
2384 #[test]
2385 fn test_maybe() {
2386 assert!(<Option<()>>::static_variant_type().is_maybe());
2387 let m1 = Some(()).to_variant();
2388 assert_eq!(m1.type_().as_str(), "m()");
2389
2390 assert_eq!(m1.get::<Option<()>>(), Some(Some(())));
2391 assert!(m1.as_maybe().is_some());
2392
2393 let m2 = None::<()>.to_variant();
2394 assert!(m2.as_maybe().is_none());
2395 }
2396
2397 #[test]
2398 fn test_btreemap() {
2399 assert_eq!(
2400 <BTreeMap<String, u32>>::static_variant_type().as_str(),
2401 "a{su}"
2402 );
2403 let mut m = BTreeMap::new();
2405 let total = 20;
2406 for n in 0..total {
2407 let k = format!("v{n:04}");
2408 m.insert(k, n as u32);
2409 }
2410 let v = m.to_variant();
2411 let n = v.n_children();
2412 assert_eq!(total, n);
2413 for n in 0..total {
2414 let child = v
2415 .try_child_get::<DictEntry<String, u32>>(n)
2416 .unwrap()
2417 .unwrap();
2418 assert_eq!(*child.value(), n as u32);
2419 }
2420
2421 assert_eq!(BTreeMap::from_variant(&v).unwrap(), m);
2422 }
2423
2424 #[test]
2425 fn test_get() -> Result<(), Box<dyn std::error::Error>> {
2426 let u = 42u32.to_variant();
2427 assert!(u.get::<i32>().is_none());
2428 assert_eq!(u.get::<u32>().unwrap(), 42);
2429 assert!(u.try_get::<i32>().is_err());
2430 assert_eq!(u.try_get::<u32>()?, 42);
2432 Ok(())
2433 }
2434
2435 #[test]
2436 fn test_byteswap() {
2437 let u = 42u32.to_variant();
2438 assert_eq!(u.byteswap().get::<u32>().unwrap(), 704643072u32);
2439 assert_eq!(u.byteswap().byteswap().get::<u32>().unwrap(), 42u32);
2440 }
2441
2442 #[test]
2443 fn test_try_child() {
2444 let a = ["foo"].to_variant();
2445 assert!(a.try_child_value(0).is_some());
2446 assert_eq!(a.try_child_get::<String>(0).unwrap().unwrap(), "foo");
2447 assert_eq!(a.child_get::<String>(0), "foo");
2448 assert!(a.try_child_get::<u32>(0).is_err());
2449 assert!(a.try_child_value(1).is_none());
2450 assert!(a.try_child_get::<String>(1).unwrap().is_none());
2451 let u = 42u32.to_variant();
2452 assert!(u.try_child_value(0).is_none());
2453 assert!(u.try_child_get::<String>(0).unwrap().is_none());
2454 }
2455
2456 #[test]
2457 fn test_serialize() {
2458 let a = ("test", 1u8, 2u32).to_variant();
2459
2460 let bytes = a.data_as_bytes();
2461 let data = a.data();
2462 let len = a.size();
2463 assert_eq!(bytes.len(), len);
2464 assert_eq!(data.len(), len);
2465
2466 let mut store_data = vec![0u8; len];
2467 assert_eq!(a.store(&mut store_data).unwrap(), len);
2468
2469 assert_eq!(&bytes, data);
2470 assert_eq!(&store_data, data);
2471
2472 let b = Variant::from_data::<(String, u8, u32), _>(store_data);
2473 assert_eq!(a, b);
2474
2475 let c = Variant::from_bytes::<(String, u8, u32)>(&bytes);
2476 assert_eq!(a, c);
2477 }
2478
2479 #[test]
2480 fn test_print_parse() {
2481 let a = ("test", 1u8, 2u32).to_variant();
2482
2483 let a2 = Variant::parse(Some(a.type_()), &a.print(false)).unwrap();
2484 assert_eq!(a, a2);
2485
2486 let a3: Variant = a.to_string().parse().unwrap();
2487 assert_eq!(a, a3);
2488 }
2489
2490 #[cfg(any(unix, windows))]
2491 #[test]
2492 fn test_paths() {
2493 use std::path::PathBuf;
2494
2495 let path = PathBuf::from("foo");
2496 let v = path.to_variant();
2497 assert_eq!(PathBuf::from_variant(&v), Some(path));
2498 }
2499
2500 #[test]
2501 fn test_regression_from_variant_panics() {
2502 let variant = "text".to_variant();
2503 let hashmap: Option<HashMap<u64, u64>> = FromVariant::from_variant(&variant);
2504 assert!(hashmap.is_none());
2505
2506 let variant = HashMap::<u64, u64>::new().to_variant();
2507 let hashmap: Option<HashMap<u64, u64>> = FromVariant::from_variant(&variant);
2508 assert!(hashmap.is_some());
2509 }
2510}