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