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