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")]
149 pub struct Variant(Shared<ffi::GVariant>);
150
151 match fn {
152 ref => |ptr| ffi::g_variant_ref_sink(ptr),
153 unref => |ptr| ffi::g_variant_unref(ptr),
154 }
155}
156
157impl StaticType for Variant {
158 #[inline]
159 fn static_type() -> Type {
160 Type::VARIANT
161 }
162}
163
164#[doc(hidden)]
165impl crate::value::ValueType for Variant {
166 type Type = Variant;
167}
168
169#[doc(hidden)]
170impl crate::value::ValueTypeOptional for Variant {}
171
172#[doc(hidden)]
173unsafe impl<'a> crate::value::FromValue<'a> for Variant {
174 type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
175
176 unsafe fn from_value(value: &'a crate::Value) -> Self {
177 unsafe {
178 let ptr = gobject_ffi::g_value_dup_variant(value.to_glib_none().0);
179 debug_assert!(!ptr.is_null());
180 from_glib_full(ptr)
181 }
182 }
183}
184
185#[doc(hidden)]
186impl crate::value::ToValue for Variant {
187 fn to_value(&self) -> crate::Value {
188 unsafe {
189 let mut value = crate::Value::from_type_unchecked(Variant::static_type());
190 gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, self.to_glib_full());
191 value
192 }
193 }
194
195 fn value_type(&self) -> crate::Type {
196 Variant::static_type()
197 }
198}
199
200#[doc(hidden)]
201impl From<Variant> for crate::Value {
202 #[inline]
203 fn from(v: Variant) -> Self {
204 unsafe {
205 let mut value = crate::Value::from_type_unchecked(Variant::static_type());
206 gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, v.into_glib_ptr());
207 value
208 }
209 }
210}
211
212#[doc(hidden)]
213impl crate::value::ToValueOptional for Variant {
214 fn to_value_optional(s: Option<&Self>) -> crate::Value {
215 let mut value = crate::Value::for_value_type::<Self>();
216 unsafe {
217 gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, s.to_glib_full());
218 }
219
220 value
221 }
222}
223
224#[derive(Clone, PartialEq, Eq, Debug)]
228pub struct VariantTypeMismatchError {
229 pub actual: VariantType,
230 pub expected: VariantType,
231}
232
233impl VariantTypeMismatchError {
234 pub fn new(actual: VariantType, expected: VariantType) -> Self {
235 Self { actual, expected }
236 }
237}
238
239impl fmt::Display for VariantTypeMismatchError {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 write!(
242 f,
243 "Type mismatch: Expected '{}' got '{}'",
244 self.expected, self.actual
245 )
246 }
247}
248
249impl std::error::Error for VariantTypeMismatchError {}
250
251impl Variant {
252 #[doc(alias = "g_variant_get_type")]
264 pub fn type_(&self) -> &VariantTy {
265 unsafe { VariantTy::from_ptr(ffi::g_variant_get_type(self.to_glib_none().0)) }
266 }
267
268 #[inline]
271 #[doc(alias = "g_variant_is_of_type")]
272 pub fn is<T: StaticVariantType>(&self) -> bool {
273 self.is_type(&T::static_variant_type())
274 }
275
276 #[inline]
281 #[doc(alias = "g_variant_is_of_type")]
282 pub fn is_type(&self, type_: &VariantTy) -> bool {
283 unsafe {
284 from_glib(ffi::g_variant_is_of_type(
285 self.to_glib_none().0,
286 type_.to_glib_none().0,
287 ))
288 }
289 }
290
291 #[doc(alias = "g_variant_classify")]
300 pub fn classify(&self) -> crate::VariantClass {
301 unsafe { from_glib(ffi::g_variant_classify(self.to_glib_none().0)) }
302 }
303
304 #[inline]
328 pub fn get<T: FromVariant>(&self) -> Option<T> {
329 T::from_variant(self)
330 }
331
332 pub fn try_get<T: FromVariant>(&self) -> Result<T, VariantTypeMismatchError> {
335 self.get().ok_or_else(|| {
336 VariantTypeMismatchError::new(
337 self.type_().to_owned(),
338 T::static_variant_type().into_owned(),
339 )
340 })
341 }
342
343 #[inline]
346 pub fn from_variant(value: &Variant) -> Self {
347 unsafe { from_glib_none(ffi::g_variant_new_variant(value.to_glib_none().0)) }
348 }
349
350 #[inline]
355 #[doc(alias = "get_variant")]
356 pub fn as_variant(&self) -> Option<Variant> {
357 unsafe { from_glib_full(ffi::g_variant_get_variant(self.to_glib_none().0)) }
358 }
359
360 #[doc(alias = "get_child_value")]
398 #[doc(alias = "g_variant_get_child_value")]
399 #[must_use]
400 pub fn child_value(&self, index: usize) -> Variant {
401 assert!(self.is_container());
402 assert!(index < self.n_children());
403
404 unsafe { from_glib_full(ffi::g_variant_get_child_value(self.to_glib_none().0, index)) }
405 }
406
407 pub fn try_child_value(&self, index: usize) -> Option<Variant> {
413 if !(self.is_container() && index < self.n_children()) {
414 return None;
415 }
416
417 let v =
418 unsafe { from_glib_full(ffi::g_variant_get_child_value(self.to_glib_none().0, index)) };
419 Some(v)
420 }
421
422 pub fn try_child_get<T: StaticVariantType + FromVariant>(
429 &self,
430 index: usize,
431 ) -> Result<Option<T>, VariantTypeMismatchError> {
432 self.try_child_value(index).map(|v| v.try_get()).transpose()
435 }
436
437 pub fn child_get<T: StaticVariantType + FromVariant>(&self, index: usize) -> T {
446 self.child_value(index).get().unwrap()
449 }
450
451 #[doc(alias = "get_str")]
457 #[doc(alias = "g_variant_get_string")]
458 pub fn str(&self) -> Option<&str> {
459 unsafe {
460 match self.type_().as_str() {
461 "s" | "o" | "g" => {
462 let mut len = 0;
463 let ptr = ffi::g_variant_get_string(self.to_glib_none().0, &mut len);
464 if len == 0 {
465 Some("")
466 } else {
467 let ret = str::from_utf8_unchecked(slice::from_raw_parts(
468 ptr as *const u8,
469 len as _,
470 ));
471 Some(ret)
472 }
473 }
474 _ => None,
475 }
476 }
477 }
478
479 #[doc(alias = "g_variant_get_fixed_array")]
519 pub fn fixed_array<T: FixedSizeVariantType>(&self) -> Result<&[T], VariantTypeMismatchError> {
520 unsafe {
521 let expected_ty = T::static_variant_type().as_array();
522 if self.type_() != expected_ty {
523 return Err(VariantTypeMismatchError {
524 actual: self.type_().to_owned(),
525 expected: expected_ty.into_owned(),
526 });
527 }
528
529 let mut n_elements = mem::MaybeUninit::uninit();
530 let ptr = ffi::g_variant_get_fixed_array(
531 self.to_glib_none().0,
532 n_elements.as_mut_ptr(),
533 mem::size_of::<T>(),
534 );
535
536 let n_elements = n_elements.assume_init();
537 if n_elements == 0 {
538 Ok(&[])
539 } else {
540 debug_assert!(!ptr.is_null());
541 Ok(slice::from_raw_parts(ptr as *const T, n_elements))
542 }
543 }
544 }
545
546 #[doc(alias = "g_variant_new_array")]
553 pub fn array_from_iter<T: StaticVariantType>(
554 children: impl IntoIterator<Item = Variant>,
555 ) -> Self {
556 Self::array_from_iter_with_type(&T::static_variant_type(), children)
557 }
558
559 #[doc(alias = "g_variant_new_array")]
566 pub fn array_from_iter_with_type(
567 type_: &VariantTy,
568 children: impl IntoIterator<Item = impl AsRef<Variant>>,
569 ) -> Self {
570 unsafe {
571 let mut builder = mem::MaybeUninit::uninit();
572 ffi::g_variant_builder_init(builder.as_mut_ptr(), type_.as_array().to_glib_none().0);
573 let mut builder = builder.assume_init();
574 for value in children.into_iter() {
575 let value = value.as_ref();
576 if ffi::g_variant_is_of_type(value.to_glib_none().0, type_.to_glib_none().0)
577 == ffi::GFALSE
578 {
579 ffi::g_variant_builder_clear(&mut builder);
580 assert!(value.is_type(type_));
581 }
582
583 ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
584 }
585 from_glib_none(ffi::g_variant_builder_end(&mut builder))
586 }
587 }
588
589 #[doc(alias = "g_variant_new_fixed_array")]
592 pub fn array_from_fixed_array<T: FixedSizeVariantType>(array: &[T]) -> Self {
593 let type_ = T::static_variant_type();
594
595 unsafe {
596 from_glib_none(ffi::g_variant_new_fixed_array(
597 type_.as_ptr(),
598 array.as_ptr() as ffi::gconstpointer,
599 array.len(),
600 mem::size_of::<T>(),
601 ))
602 }
603 }
604
605 #[doc(alias = "g_variant_new_tuple")]
608 pub fn tuple_from_iter(children: impl IntoIterator<Item = impl AsRef<Variant>>) -> Self {
609 unsafe {
610 let mut builder = mem::MaybeUninit::uninit();
611 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
612 let mut builder = builder.assume_init();
613 for value in children.into_iter() {
614 ffi::g_variant_builder_add_value(&mut builder, value.as_ref().to_glib_none().0);
615 }
616 from_glib_none(ffi::g_variant_builder_end(&mut builder))
617 }
618 }
619
620 #[doc(alias = "g_variant_new_dict_entry")]
625 pub fn from_dict_entry(key: &Variant, value: &Variant) -> Self {
626 unsafe {
627 from_glib_none(ffi::g_variant_new_dict_entry(
628 key.to_glib_none().0,
629 value.to_glib_none().0,
630 ))
631 }
632 }
633
634 #[doc(alias = "g_variant_new_maybe")]
637 pub fn from_maybe<T: StaticVariantType>(child: Option<&Variant>) -> Self {
638 let type_ = T::static_variant_type();
639 match child {
640 Some(child) => {
641 assert_eq!(type_, child.type_());
642
643 Self::from_some(child)
644 }
645 None => Self::from_none(&type_),
646 }
647 }
648
649 #[doc(alias = "g_variant_new_maybe")]
652 pub fn from_some(child: &Variant) -> Self {
653 unsafe {
654 from_glib_none(ffi::g_variant_new_maybe(
655 ptr::null(),
656 child.to_glib_none().0,
657 ))
658 }
659 }
660
661 #[doc(alias = "g_variant_new_maybe")]
664 pub fn from_none(type_: &VariantTy) -> Self {
665 unsafe {
666 from_glib_none(ffi::g_variant_new_maybe(
667 type_.to_glib_none().0,
668 ptr::null_mut(),
669 ))
670 }
671 }
672
673 #[inline]
682 pub fn as_maybe(&self) -> Option<Variant> {
683 assert!(self.type_().is_maybe());
684
685 unsafe { from_glib_full(ffi::g_variant_get_maybe(self.to_glib_none().0)) }
686 }
687
688 #[doc(alias = "g_variant_print")]
707 pub fn print(&self, type_annotate: bool) -> crate::GString {
708 unsafe {
709 from_glib_full(ffi::g_variant_print(
710 self.to_glib_none().0,
711 type_annotate.into_glib(),
712 ))
713 }
714 }
715
716 #[doc(alias = "g_variant_parse")]
719 pub fn parse(type_: Option<&VariantTy>, text: &str) -> Result<Self, crate::Error> {
720 unsafe {
721 let mut error = ptr::null_mut();
722 let text = text.as_bytes().as_ptr_range();
723 let variant = ffi::g_variant_parse(
724 type_.to_glib_none().0,
725 text.start as *const _,
726 text.end as *const _,
727 ptr::null_mut(),
728 &mut error,
729 );
730 if variant.is_null() {
731 debug_assert!(!error.is_null());
732 Err(from_glib_full(error))
733 } else {
734 debug_assert!(error.is_null());
735 Ok(from_glib_full(variant))
736 }
737 }
738 }
739
740 #[doc(alias = "g_variant_new_from_bytes")]
763 pub fn from_bytes<T: StaticVariantType>(bytes: &Bytes) -> Self {
764 Variant::from_bytes_with_type(bytes, &T::static_variant_type())
765 }
766
767 pub unsafe fn from_bytes_trusted<T: StaticVariantType>(bytes: &Bytes) -> Self {
781 unsafe { Variant::from_bytes_with_type_trusted(bytes, &T::static_variant_type()) }
782 }
783
784 #[doc(alias = "g_variant_new_from_data")]
829 pub fn from_data<T: StaticVariantType, A: AsRef<[u8]> + 'static>(data: A) -> Self {
830 Variant::from_data_with_type(data, &T::static_variant_type())
831 }
832
833 pub unsafe fn from_data_trusted<T: StaticVariantType, A: AsRef<[u8]> + 'static>(
847 data: A,
848 ) -> Self {
849 unsafe { Variant::from_data_with_type_trusted(data, &T::static_variant_type()) }
850 }
851
852 #[doc(alias = "g_variant_new_from_bytes")]
855 pub fn from_bytes_with_type(bytes: &Bytes, type_: &VariantTy) -> Self {
856 unsafe {
857 from_glib_none(ffi::g_variant_new_from_bytes(
858 type_.as_ptr() as *const _,
859 bytes.to_glib_none().0,
860 false.into_glib(),
861 ))
862 }
863 }
864
865 pub unsafe fn from_bytes_with_type_trusted(bytes: &Bytes, type_: &VariantTy) -> Self {
879 unsafe {
880 from_glib_none(ffi::g_variant_new_from_bytes(
881 type_.as_ptr() as *const _,
882 bytes.to_glib_none().0,
883 true.into_glib(),
884 ))
885 }
886 }
887
888 #[doc(alias = "g_variant_new_from_data")]
891 pub fn from_data_with_type<A: AsRef<[u8]> + 'static>(data: A, type_: &VariantTy) -> Self {
892 unsafe {
893 let data = Box::new(data);
894 let (data_ptr, len) = {
895 let data = (*data).as_ref();
896 (data.as_ptr(), data.len())
897 };
898
899 unsafe extern "C" fn free_data<A: AsRef<[u8]>>(ptr: ffi::gpointer) {
900 unsafe {
901 let _ = Box::from_raw(ptr as *mut A);
902 }
903 }
904
905 from_glib_none(ffi::g_variant_new_from_data(
906 type_.as_ptr() as *const _,
907 data_ptr as ffi::gconstpointer,
908 len,
909 false.into_glib(),
910 Some(free_data::<A>),
911 Box::into_raw(data) as ffi::gpointer,
912 ))
913 }
914 }
915
916 pub unsafe fn from_data_with_type_trusted<A: AsRef<[u8]> + 'static>(
930 data: A,
931 type_: &VariantTy,
932 ) -> Self {
933 unsafe {
934 let data = Box::new(data);
935 let (data_ptr, len) = {
936 let data = (*data).as_ref();
937 (data.as_ptr(), data.len())
938 };
939
940 unsafe extern "C" fn free_data<A: AsRef<[u8]>>(ptr: ffi::gpointer) {
941 unsafe {
942 let _ = Box::from_raw(ptr as *mut A);
943 }
944 }
945
946 from_glib_none(ffi::g_variant_new_from_data(
947 type_.as_ptr() as *const _,
948 data_ptr as ffi::gconstpointer,
949 len,
950 true.into_glib(),
951 Some(free_data::<A>),
952 Box::into_raw(data) as ffi::gpointer,
953 ))
954 }
955 }
956
957 #[doc(alias = "get_data_as_bytes")]
969 #[doc(alias = "g_variant_get_data_as_bytes")]
970 pub fn data_as_bytes(&self) -> Bytes {
971 unsafe { from_glib_full(ffi::g_variant_get_data_as_bytes(self.to_glib_none().0)) }
972 }
973
974 #[doc(alias = "g_variant_get_data")]
1007 pub fn data(&self) -> &[u8] {
1008 unsafe {
1009 let selfv = self.to_glib_none();
1010 let len = ffi::g_variant_get_size(selfv.0);
1011 if len == 0 {
1012 return &[];
1013 }
1014 let ptr = ffi::g_variant_get_data(selfv.0);
1015 slice::from_raw_parts(ptr as *const _, len as _)
1016 }
1017 }
1018
1019 #[doc(alias = "g_variant_get_size")]
1038 pub fn size(&self) -> usize {
1039 unsafe { ffi::g_variant_get_size(self.to_glib_none().0) }
1040 }
1041
1042 #[doc(alias = "g_variant_store")]
1060 pub fn store(&self, data: &mut [u8]) -> Result<usize, crate::BoolError> {
1061 unsafe {
1062 let size = ffi::g_variant_get_size(self.to_glib_none().0);
1063 if data.len() < size {
1064 return Err(bool_error!("Provided slice is too small"));
1065 }
1066
1067 ffi::g_variant_store(self.to_glib_none().0, data.as_mut_ptr() as ffi::gpointer);
1068
1069 Ok(size)
1070 }
1071 }
1072
1073 #[doc(alias = "g_variant_get_normal_form")]
1106 #[must_use]
1107 pub fn normal_form(&self) -> Self {
1108 unsafe { from_glib_full(ffi::g_variant_get_normal_form(self.to_glib_none().0)) }
1109 }
1110
1111 #[doc(alias = "g_variant_byteswap")]
1136 #[must_use]
1137 pub fn byteswap(&self) -> Self {
1138 unsafe { from_glib_full(ffi::g_variant_byteswap(self.to_glib_none().0)) }
1139 }
1140
1141 #[doc(alias = "g_variant_n_children")]
1160 pub fn n_children(&self) -> usize {
1161 assert!(self.is_container());
1162
1163 unsafe { ffi::g_variant_n_children(self.to_glib_none().0) }
1164 }
1165
1166 pub fn iter(&self) -> VariantIter {
1172 assert!(self.is_container());
1173
1174 VariantIter::new(self.clone())
1175 }
1176
1177 pub fn array_iter_str(&self) -> Result<VariantStrIter<'_>, VariantTypeMismatchError> {
1196 let child_ty = String::static_variant_type();
1197 let actual_ty = self.type_();
1198 let expected_ty = child_ty.as_array();
1199 if actual_ty != expected_ty {
1200 return Err(VariantTypeMismatchError {
1201 actual: actual_ty.to_owned(),
1202 expected: expected_ty.into_owned(),
1203 });
1204 }
1205
1206 Ok(VariantStrIter::new(self))
1207 }
1208
1209 #[doc(alias = "g_variant_is_container")]
1218 pub fn is_container(&self) -> bool {
1219 unsafe { from_glib(ffi::g_variant_is_container(self.to_glib_none().0)) }
1220 }
1221
1222 #[doc(alias = "g_variant_is_normal_form")]
1243 pub fn is_normal_form(&self) -> bool {
1244 unsafe { from_glib(ffi::g_variant_is_normal_form(self.to_glib_none().0)) }
1245 }
1246
1247 #[doc(alias = "g_variant_is_object_path")]
1265 pub fn is_object_path(string: &str) -> bool {
1266 unsafe { from_glib(ffi::g_variant_is_object_path(string.to_glib_none().0)) }
1267 }
1268
1269 #[doc(alias = "g_variant_is_signature")]
1285 pub fn is_signature(string: &str) -> bool {
1286 unsafe { from_glib(ffi::g_variant_is_signature(string.to_glib_none().0)) }
1287 }
1288}
1289
1290unsafe impl Send for Variant {}
1291unsafe impl Sync for Variant {}
1292
1293impl fmt::Debug for Variant {
1294 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1295 f.debug_struct("Variant")
1296 .field("ptr", &ToGlibPtr::<*const _>::to_glib_none(self).0)
1297 .field("type", &self.type_())
1298 .field("value", &self.to_string())
1299 .finish()
1300 }
1301}
1302
1303impl fmt::Display for Variant {
1304 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1305 f.write_str(&self.print(true))
1306 }
1307}
1308
1309impl str::FromStr for Variant {
1310 type Err = crate::Error;
1311
1312 fn from_str(s: &str) -> Result<Self, Self::Err> {
1313 Self::parse(None, s)
1314 }
1315}
1316
1317impl PartialEq for Variant {
1318 #[doc(alias = "g_variant_equal")]
1319 fn eq(&self, other: &Self) -> bool {
1320 unsafe {
1321 from_glib(ffi::g_variant_equal(
1322 ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
1323 ToGlibPtr::<*const _>::to_glib_none(other).0 as *const _,
1324 ))
1325 }
1326 }
1327}
1328
1329impl Eq for Variant {}
1330
1331impl PartialOrd for Variant {
1332 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1333 unsafe {
1334 if ffi::g_variant_classify(self.to_glib_none().0)
1335 != ffi::g_variant_classify(other.to_glib_none().0)
1336 {
1337 return None;
1338 }
1339
1340 if self.is_container() {
1341 return None;
1342 }
1343
1344 let res = ffi::g_variant_compare(
1345 ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
1346 ToGlibPtr::<*const _>::to_glib_none(other).0 as *const _,
1347 );
1348
1349 Some(res.cmp(&0))
1350 }
1351 }
1352}
1353
1354impl Hash for Variant {
1355 #[doc(alias = "g_variant_hash")]
1356 fn hash<H: Hasher>(&self, state: &mut H) {
1357 unsafe {
1358 state.write_u32(ffi::g_variant_hash(
1359 ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
1360 ))
1361 }
1362 }
1363}
1364
1365impl AsRef<Variant> for Variant {
1366 #[inline]
1367 fn as_ref(&self) -> &Self {
1368 self
1369 }
1370}
1371
1372pub trait ToVariant {
1375 fn to_variant(&self) -> Variant;
1378}
1379
1380pub trait FromVariant: Sized + StaticVariantType {
1383 fn from_variant(variant: &Variant) -> Option<Self>;
1388}
1389
1390pub trait StaticVariantType {
1393 fn static_variant_type() -> Cow<'static, VariantTy>;
1396}
1397
1398impl StaticVariantType for Variant {
1399 fn static_variant_type() -> Cow<'static, VariantTy> {
1400 Cow::Borrowed(VariantTy::VARIANT)
1401 }
1402}
1403
1404impl<T: ?Sized + ToVariant> ToVariant for &T {
1405 fn to_variant(&self) -> Variant {
1406 <T as ToVariant>::to_variant(self)
1407 }
1408}
1409
1410impl<'a, T: Into<Variant> + Clone> From<&'a T> for Variant {
1411 #[inline]
1412 fn from(v: &'a T) -> Self {
1413 v.clone().into()
1414 }
1415}
1416
1417impl<T: ?Sized + StaticVariantType> StaticVariantType for &T {
1418 fn static_variant_type() -> Cow<'static, VariantTy> {
1419 <T as StaticVariantType>::static_variant_type()
1420 }
1421}
1422
1423macro_rules! impl_numeric {
1424 ($name:ty, $typ:expr, $new_fn:ident, $get_fn:ident) => {
1425 impl StaticVariantType for $name {
1426 fn static_variant_type() -> Cow<'static, VariantTy> {
1427 Cow::Borrowed($typ)
1428 }
1429 }
1430
1431 impl ToVariant for $name {
1432 fn to_variant(&self) -> Variant {
1433 unsafe { from_glib_none(ffi::$new_fn(*self)) }
1434 }
1435 }
1436
1437 impl From<$name> for Variant {
1438 #[inline]
1439 fn from(v: $name) -> Self {
1440 v.to_variant()
1441 }
1442 }
1443
1444 impl FromVariant for $name {
1445 fn from_variant(variant: &Variant) -> Option<Self> {
1446 unsafe {
1447 if variant.is::<Self>() {
1448 Some(ffi::$get_fn(variant.to_glib_none().0))
1449 } else {
1450 None
1451 }
1452 }
1453 }
1454 }
1455 };
1456}
1457
1458impl_numeric!(u8, VariantTy::BYTE, g_variant_new_byte, g_variant_get_byte);
1459impl_numeric!(
1460 i16,
1461 VariantTy::INT16,
1462 g_variant_new_int16,
1463 g_variant_get_int16
1464);
1465impl_numeric!(
1466 u16,
1467 VariantTy::UINT16,
1468 g_variant_new_uint16,
1469 g_variant_get_uint16
1470);
1471impl_numeric!(
1472 i32,
1473 VariantTy::INT32,
1474 g_variant_new_int32,
1475 g_variant_get_int32
1476);
1477impl_numeric!(
1478 u32,
1479 VariantTy::UINT32,
1480 g_variant_new_uint32,
1481 g_variant_get_uint32
1482);
1483impl_numeric!(
1484 i64,
1485 VariantTy::INT64,
1486 g_variant_new_int64,
1487 g_variant_get_int64
1488);
1489impl_numeric!(
1490 u64,
1491 VariantTy::UINT64,
1492 g_variant_new_uint64,
1493 g_variant_get_uint64
1494);
1495impl_numeric!(
1496 f64,
1497 VariantTy::DOUBLE,
1498 g_variant_new_double,
1499 g_variant_get_double
1500);
1501
1502impl StaticVariantType for () {
1503 fn static_variant_type() -> Cow<'static, VariantTy> {
1504 Cow::Borrowed(VariantTy::UNIT)
1505 }
1506}
1507
1508impl ToVariant for () {
1509 fn to_variant(&self) -> Variant {
1510 unsafe { from_glib_none(ffi::g_variant_new_tuple(ptr::null(), 0)) }
1511 }
1512}
1513
1514impl From<()> for Variant {
1515 #[inline]
1516 fn from(_: ()) -> Self {
1517 ().to_variant()
1518 }
1519}
1520
1521impl FromVariant for () {
1522 fn from_variant(variant: &Variant) -> Option<Self> {
1523 if variant.is::<Self>() { Some(()) } else { None }
1524 }
1525}
1526
1527impl StaticVariantType for bool {
1528 fn static_variant_type() -> Cow<'static, VariantTy> {
1529 Cow::Borrowed(VariantTy::BOOLEAN)
1530 }
1531}
1532
1533impl ToVariant for bool {
1534 fn to_variant(&self) -> Variant {
1535 unsafe { from_glib_none(ffi::g_variant_new_boolean(self.into_glib())) }
1536 }
1537}
1538
1539impl From<bool> for Variant {
1540 #[inline]
1541 fn from(v: bool) -> Self {
1542 v.to_variant()
1543 }
1544}
1545
1546impl FromVariant for bool {
1547 fn from_variant(variant: &Variant) -> Option<Self> {
1548 unsafe {
1549 if variant.is::<Self>() {
1550 Some(from_glib(ffi::g_variant_get_boolean(
1551 variant.to_glib_none().0,
1552 )))
1553 } else {
1554 None
1555 }
1556 }
1557 }
1558}
1559
1560impl StaticVariantType for String {
1561 fn static_variant_type() -> Cow<'static, VariantTy> {
1562 Cow::Borrowed(VariantTy::STRING)
1563 }
1564}
1565
1566impl ToVariant for String {
1567 fn to_variant(&self) -> Variant {
1568 self[..].to_variant()
1569 }
1570}
1571
1572impl From<String> for Variant {
1573 #[inline]
1574 fn from(s: String) -> Self {
1575 s.to_variant()
1576 }
1577}
1578
1579impl FromVariant for String {
1580 fn from_variant(variant: &Variant) -> Option<Self> {
1581 variant.str().map(String::from)
1582 }
1583}
1584
1585impl StaticVariantType for str {
1586 fn static_variant_type() -> Cow<'static, VariantTy> {
1587 String::static_variant_type()
1588 }
1589}
1590
1591impl ToVariant for str {
1592 fn to_variant(&self) -> Variant {
1593 unsafe { from_glib_none(ffi::g_variant_new_take_string(self.to_glib_full())) }
1594 }
1595}
1596
1597impl From<&str> for Variant {
1598 #[inline]
1599 fn from(s: &str) -> Self {
1600 s.to_variant()
1601 }
1602}
1603
1604impl StaticVariantType for std::path::PathBuf {
1605 fn static_variant_type() -> Cow<'static, VariantTy> {
1606 std::path::Path::static_variant_type()
1607 }
1608}
1609
1610impl ToVariant for std::path::PathBuf {
1611 fn to_variant(&self) -> Variant {
1612 self.as_path().to_variant()
1613 }
1614}
1615
1616impl From<std::path::PathBuf> for Variant {
1617 #[inline]
1618 fn from(p: std::path::PathBuf) -> Self {
1619 p.to_variant()
1620 }
1621}
1622
1623impl FromVariant for std::path::PathBuf {
1624 fn from_variant(variant: &Variant) -> Option<Self> {
1625 unsafe {
1626 let ptr = ffi::g_variant_get_bytestring(variant.to_glib_none().0);
1627 Some(crate::translate::c_to_path_buf(ptr as *const _))
1628 }
1629 }
1630}
1631
1632impl StaticVariantType for std::path::Path {
1633 fn static_variant_type() -> Cow<'static, VariantTy> {
1634 <&[u8]>::static_variant_type()
1635 }
1636}
1637
1638impl ToVariant for std::path::Path {
1639 fn to_variant(&self) -> Variant {
1640 let tmp = crate::translate::path_to_c(self);
1641 unsafe { from_glib_none(ffi::g_variant_new_bytestring(tmp.as_ptr() as *const u8)) }
1642 }
1643}
1644
1645impl From<&std::path::Path> for Variant {
1646 #[inline]
1647 fn from(p: &std::path::Path) -> Self {
1648 p.to_variant()
1649 }
1650}
1651
1652impl StaticVariantType for std::ffi::OsString {
1653 fn static_variant_type() -> Cow<'static, VariantTy> {
1654 std::ffi::OsStr::static_variant_type()
1655 }
1656}
1657
1658impl ToVariant for std::ffi::OsString {
1659 fn to_variant(&self) -> Variant {
1660 self.as_os_str().to_variant()
1661 }
1662}
1663
1664impl From<std::ffi::OsString> for Variant {
1665 #[inline]
1666 fn from(s: std::ffi::OsString) -> Self {
1667 s.to_variant()
1668 }
1669}
1670
1671impl FromVariant for std::ffi::OsString {
1672 fn from_variant(variant: &Variant) -> Option<Self> {
1673 unsafe {
1674 let ptr = ffi::g_variant_get_bytestring(variant.to_glib_none().0);
1675 Some(crate::translate::c_to_os_string(ptr as *const _))
1676 }
1677 }
1678}
1679
1680impl StaticVariantType for std::ffi::OsStr {
1681 fn static_variant_type() -> Cow<'static, VariantTy> {
1682 <&[u8]>::static_variant_type()
1683 }
1684}
1685
1686impl ToVariant for std::ffi::OsStr {
1687 fn to_variant(&self) -> Variant {
1688 let tmp = crate::translate::os_str_to_c(self);
1689 unsafe { from_glib_none(ffi::g_variant_new_bytestring(tmp.as_ptr() as *const u8)) }
1690 }
1691}
1692
1693impl From<&std::ffi::OsStr> for Variant {
1694 #[inline]
1695 fn from(s: &std::ffi::OsStr) -> Self {
1696 s.to_variant()
1697 }
1698}
1699
1700impl<T: StaticVariantType> StaticVariantType for Option<T> {
1701 fn static_variant_type() -> Cow<'static, VariantTy> {
1702 Cow::Owned(VariantType::new_maybe(&T::static_variant_type()))
1703 }
1704}
1705
1706impl<T: StaticVariantType + ToVariant> ToVariant for Option<T> {
1707 fn to_variant(&self) -> Variant {
1708 Variant::from_maybe::<T>(self.as_ref().map(|m| m.to_variant()).as_ref())
1709 }
1710}
1711
1712impl<T: StaticVariantType + Into<Variant>> From<Option<T>> for Variant {
1713 #[inline]
1714 fn from(v: Option<T>) -> Self {
1715 Variant::from_maybe::<T>(v.map(|v| v.into()).as_ref())
1716 }
1717}
1718
1719impl<T: StaticVariantType + FromVariant> FromVariant for Option<T> {
1720 fn from_variant(variant: &Variant) -> Option<Self> {
1721 unsafe {
1722 if variant.is::<Self>() {
1723 let c_child = ffi::g_variant_get_maybe(variant.to_glib_none().0);
1724 if !c_child.is_null() {
1725 let child: Variant = from_glib_full(c_child);
1726
1727 Some(T::from_variant(&child))
1728 } else {
1729 Some(None)
1730 }
1731 } else {
1732 None
1733 }
1734 }
1735 }
1736}
1737
1738impl<T: StaticVariantType> StaticVariantType for [T] {
1739 fn static_variant_type() -> Cow<'static, VariantTy> {
1740 T::static_variant_type().as_array()
1741 }
1742}
1743
1744impl<T: StaticVariantType + ToVariant> ToVariant for [T] {
1745 fn to_variant(&self) -> Variant {
1746 unsafe {
1747 if self.is_empty() {
1748 return from_glib_none(ffi::g_variant_new_array(
1749 T::static_variant_type().to_glib_none().0,
1750 ptr::null(),
1751 0,
1752 ));
1753 }
1754
1755 let mut builder = mem::MaybeUninit::uninit();
1756 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1757 let mut builder = builder.assume_init();
1758 for value in self {
1759 let value = value.to_variant();
1760 ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
1761 }
1762 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1763 }
1764 }
1765}
1766
1767impl<T: StaticVariantType + ToVariant> From<&[T]> for Variant {
1768 #[inline]
1769 fn from(s: &[T]) -> Self {
1770 s.to_variant()
1771 }
1772}
1773
1774impl<T: FromVariant> FromVariant for Vec<T> {
1775 fn from_variant(variant: &Variant) -> Option<Self> {
1776 if !variant.is_container() {
1777 return None;
1778 }
1779
1780 let mut vec = Vec::with_capacity(variant.n_children());
1781
1782 for i in 0..variant.n_children() {
1783 match variant.child_value(i).get() {
1784 Some(child) => vec.push(child),
1785 None => return None,
1786 }
1787 }
1788
1789 Some(vec)
1790 }
1791}
1792
1793impl<T: StaticVariantType + ToVariant> ToVariant for Vec<T> {
1794 fn to_variant(&self) -> Variant {
1795 self.as_slice().to_variant()
1796 }
1797}
1798
1799impl<T: StaticVariantType + Into<Variant>> From<Vec<T>> for Variant {
1800 fn from(v: Vec<T>) -> Self {
1801 unsafe {
1802 if v.is_empty() {
1803 return from_glib_none(ffi::g_variant_new_array(
1804 T::static_variant_type().to_glib_none().0,
1805 ptr::null(),
1806 0,
1807 ));
1808 }
1809
1810 let mut builder = mem::MaybeUninit::uninit();
1811 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1812 let mut builder = builder.assume_init();
1813 for value in v {
1814 let value = value.into();
1815 ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
1816 }
1817 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1818 }
1819 }
1820}
1821
1822impl<T: StaticVariantType> StaticVariantType for Vec<T> {
1823 fn static_variant_type() -> Cow<'static, VariantTy> {
1824 <[T]>::static_variant_type()
1825 }
1826}
1827
1828impl<K, V, H> FromVariant for HashMap<K, V, H>
1829where
1830 K: FromVariant + Eq + Hash,
1831 V: FromVariant,
1832 H: BuildHasher + Default,
1833{
1834 fn from_variant(variant: &Variant) -> Option<Self> {
1835 if !variant.is_container() {
1836 return None;
1837 }
1838
1839 let mut map = HashMap::default();
1840
1841 for i in 0..variant.n_children() {
1842 let entry = variant.child_value(i);
1843 let key = entry.child_value(0).get()?;
1844 let val = entry.child_value(1).get()?;
1845
1846 map.insert(key, val);
1847 }
1848
1849 Some(map)
1850 }
1851}
1852
1853impl<K, V> FromVariant for BTreeMap<K, V>
1854where
1855 K: FromVariant + Eq + Ord,
1856 V: FromVariant,
1857{
1858 fn from_variant(variant: &Variant) -> Option<Self> {
1859 if !variant.is_container() {
1860 return None;
1861 }
1862
1863 let mut map = BTreeMap::default();
1864
1865 for i in 0..variant.n_children() {
1866 let entry = variant.child_value(i);
1867 let key = entry.child_value(0).get()?;
1868 let val = entry.child_value(1).get()?;
1869
1870 map.insert(key, val);
1871 }
1872
1873 Some(map)
1874 }
1875}
1876
1877impl<K, V> ToVariant for HashMap<K, V>
1878where
1879 K: StaticVariantType + ToVariant + Eq + Hash,
1880 V: StaticVariantType + ToVariant,
1881{
1882 fn to_variant(&self) -> Variant {
1883 unsafe {
1884 if self.is_empty() {
1885 return from_glib_none(ffi::g_variant_new_array(
1886 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
1887 ptr::null(),
1888 0,
1889 ));
1890 }
1891
1892 let mut builder = mem::MaybeUninit::uninit();
1893 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1894 let mut builder = builder.assume_init();
1895 for (key, value) in self {
1896 let entry = DictEntry::new(key, value).to_variant();
1897 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
1898 }
1899 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1900 }
1901 }
1902}
1903
1904impl<K, V> From<HashMap<K, V>> for Variant
1905where
1906 K: StaticVariantType + Into<Variant> + Eq + Hash,
1907 V: StaticVariantType + Into<Variant>,
1908{
1909 fn from(m: HashMap<K, V>) -> Self {
1910 unsafe {
1911 if m.is_empty() {
1912 return from_glib_none(ffi::g_variant_new_array(
1913 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
1914 ptr::null(),
1915 0,
1916 ));
1917 }
1918
1919 let mut builder = mem::MaybeUninit::uninit();
1920 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1921 let mut builder = builder.assume_init();
1922 for (key, value) in m {
1923 let entry = Variant::from(DictEntry::new(key, value));
1924 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
1925 }
1926 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1927 }
1928 }
1929}
1930
1931impl<K, V> ToVariant for BTreeMap<K, V>
1932where
1933 K: StaticVariantType + ToVariant + Eq + Hash,
1934 V: StaticVariantType + ToVariant,
1935{
1936 fn to_variant(&self) -> Variant {
1937 unsafe {
1938 if self.is_empty() {
1939 return from_glib_none(ffi::g_variant_new_array(
1940 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
1941 ptr::null(),
1942 0,
1943 ));
1944 }
1945
1946 let mut builder = mem::MaybeUninit::uninit();
1947 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1948 let mut builder = builder.assume_init();
1949 for (key, value) in self {
1950 let entry = DictEntry::new(key, value).to_variant();
1951 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
1952 }
1953 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1954 }
1955 }
1956}
1957
1958impl<K, V> From<BTreeMap<K, V>> for Variant
1959where
1960 K: StaticVariantType + Into<Variant> + Eq + Hash,
1961 V: StaticVariantType + Into<Variant>,
1962{
1963 fn from(m: BTreeMap<K, V>) -> Self {
1964 unsafe {
1965 if m.is_empty() {
1966 return from_glib_none(ffi::g_variant_new_array(
1967 DictEntry::<K, V>::static_variant_type().to_glib_none().0,
1968 ptr::null(),
1969 0,
1970 ));
1971 }
1972
1973 let mut builder = mem::MaybeUninit::uninit();
1974 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
1975 let mut builder = builder.assume_init();
1976 for (key, value) in m {
1977 let entry = Variant::from(DictEntry::new(key, value));
1978 ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
1979 }
1980 from_glib_none(ffi::g_variant_builder_end(&mut builder))
1981 }
1982 }
1983}
1984
1985#[derive(Debug, Clone)]
2004pub struct DictEntry<K, V> {
2005 key: K,
2006 value: V,
2007}
2008
2009impl<K, V> DictEntry<K, V>
2010where
2011 K: StaticVariantType,
2012 V: StaticVariantType,
2013{
2014 pub fn new(key: K, value: V) -> Self {
2015 Self { key, value }
2016 }
2017
2018 pub fn key(&self) -> &K {
2019 &self.key
2020 }
2021
2022 pub fn value(&self) -> &V {
2023 &self.value
2024 }
2025}
2026
2027impl<K, V> FromVariant for DictEntry<K, V>
2028where
2029 K: FromVariant,
2030 V: FromVariant,
2031{
2032 fn from_variant(variant: &Variant) -> Option<Self> {
2033 if !variant.type_().is_subtype_of(VariantTy::DICT_ENTRY) {
2034 return None;
2035 }
2036
2037 let key = variant.child_value(0).get()?;
2038 let value = variant.child_value(1).get()?;
2039
2040 Some(Self { key, value })
2041 }
2042}
2043
2044impl<K, V> ToVariant for DictEntry<K, V>
2045where
2046 K: StaticVariantType + ToVariant,
2047 V: StaticVariantType + ToVariant,
2048{
2049 fn to_variant(&self) -> Variant {
2050 Variant::from_dict_entry(&self.key.to_variant(), &self.value.to_variant())
2051 }
2052}
2053
2054impl<K, V> From<DictEntry<K, V>> for Variant
2055where
2056 K: StaticVariantType + Into<Variant>,
2057 V: StaticVariantType + Into<Variant>,
2058{
2059 fn from(e: DictEntry<K, V>) -> Self {
2060 Variant::from_dict_entry(&e.key.into(), &e.value.into())
2061 }
2062}
2063
2064impl ToVariant for Variant {
2065 fn to_variant(&self) -> Variant {
2066 Variant::from_variant(self)
2067 }
2068}
2069
2070impl FromVariant for Variant {
2071 fn from_variant(variant: &Variant) -> Option<Self> {
2072 variant.as_variant()
2073 }
2074}
2075
2076impl<K: StaticVariantType, V: StaticVariantType> StaticVariantType for DictEntry<K, V> {
2077 fn static_variant_type() -> Cow<'static, VariantTy> {
2078 Cow::Owned(VariantType::new_dict_entry(
2079 &K::static_variant_type(),
2080 &V::static_variant_type(),
2081 ))
2082 }
2083}
2084
2085fn static_variant_mapping<K, V>() -> Cow<'static, VariantTy>
2086where
2087 K: StaticVariantType,
2088 V: StaticVariantType,
2089{
2090 use std::fmt::Write;
2091
2092 let key_type = K::static_variant_type();
2093 let value_type = V::static_variant_type();
2094
2095 if key_type == VariantTy::STRING && value_type == VariantTy::VARIANT {
2096 return Cow::Borrowed(VariantTy::VARDICT);
2097 }
2098
2099 let mut builder = crate::GStringBuilder::default();
2100 write!(builder, "a{{{}{}}}", key_type.as_str(), value_type.as_str()).unwrap();
2101
2102 Cow::Owned(VariantType::from_string(builder.into_string()).unwrap())
2103}
2104
2105impl<K, V, H> StaticVariantType for HashMap<K, V, H>
2106where
2107 K: StaticVariantType,
2108 V: StaticVariantType,
2109 H: BuildHasher + Default,
2110{
2111 fn static_variant_type() -> Cow<'static, VariantTy> {
2112 static_variant_mapping::<K, V>()
2113 }
2114}
2115
2116impl<K, V> StaticVariantType for BTreeMap<K, V>
2117where
2118 K: StaticVariantType,
2119 V: StaticVariantType,
2120{
2121 fn static_variant_type() -> Cow<'static, VariantTy> {
2122 static_variant_mapping::<K, V>()
2123 }
2124}
2125
2126macro_rules! tuple_impls {
2127 ($($len:expr => ($($n:tt $name:ident)+))+) => {
2128 $(
2129 impl<$($name),+> StaticVariantType for ($($name,)+)
2130 where
2131 $($name: StaticVariantType,)+
2132 {
2133 fn static_variant_type() -> Cow<'static, VariantTy> {
2134 Cow::Owned(VariantType::new_tuple(&[
2135 $(
2136 $name::static_variant_type(),
2137 )+
2138 ]))
2139 }
2140 }
2141
2142 impl<$($name),+> FromVariant for ($($name,)+)
2143 where
2144 $($name: FromVariant,)+
2145 {
2146 fn from_variant(variant: &Variant) -> Option<Self> {
2147 if !variant.type_().is_subtype_of(VariantTy::TUPLE) {
2148 return None;
2149 }
2150
2151 Some((
2152 $(
2153 match variant.try_child_get::<$name>($n) {
2154 Ok(Some(field)) => field,
2155 _ => return None,
2156 },
2157 )+
2158 ))
2159 }
2160 }
2161
2162 impl<$($name),+> ToVariant for ($($name,)+)
2163 where
2164 $($name: ToVariant,)+
2165 {
2166 fn to_variant(&self) -> Variant {
2167 unsafe {
2168 let mut builder = mem::MaybeUninit::uninit();
2169 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
2170 let mut builder = builder.assume_init();
2171
2172 $(
2173 let field = self.$n.to_variant();
2174 ffi::g_variant_builder_add_value(&mut builder, field.to_glib_none().0);
2175 )+
2176
2177 from_glib_none(ffi::g_variant_builder_end(&mut builder))
2178 }
2179 }
2180 }
2181
2182 impl<$($name),+> From<($($name,)+)> for Variant
2183 where
2184 $($name: Into<Variant>,)+
2185 {
2186 fn from(t: ($($name,)+)) -> Self {
2187 unsafe {
2188 let mut builder = mem::MaybeUninit::uninit();
2189 ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
2190 let mut builder = builder.assume_init();
2191
2192 $(
2193 let field = t.$n.into();
2194 ffi::g_variant_builder_add_value(&mut builder, field.to_glib_none().0);
2195 )+
2196
2197 from_glib_none(ffi::g_variant_builder_end(&mut builder))
2198 }
2199 }
2200 }
2201 )+
2202 }
2203}
2204
2205tuple_impls! {
2206 1 => (0 T0)
2207 2 => (0 T0 1 T1)
2208 3 => (0 T0 1 T1 2 T2)
2209 4 => (0 T0 1 T1 2 T2 3 T3)
2210 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
2211 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
2212 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
2213 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
2214 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
2215 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
2216 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
2217 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)
2218 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)
2219 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)
2220 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)
2221 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)
2222}
2223
2224impl<T: Into<Variant> + StaticVariantType> FromIterator<T> for Variant {
2225 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
2226 Variant::array_from_iter::<T>(iter.into_iter().map(|v| v.into()))
2227 }
2228}
2229
2230pub unsafe trait FixedSizeVariantType: StaticVariantType + Sized + Copy {}
2232unsafe impl FixedSizeVariantType for u8 {}
2233unsafe impl FixedSizeVariantType for i16 {}
2234unsafe impl FixedSizeVariantType for u16 {}
2235unsafe impl FixedSizeVariantType for i32 {}
2236unsafe impl FixedSizeVariantType for u32 {}
2237unsafe impl FixedSizeVariantType for i64 {}
2238unsafe impl FixedSizeVariantType for u64 {}
2239unsafe impl FixedSizeVariantType for f64 {}
2240unsafe impl FixedSizeVariantType for bool {}
2241
2242#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2250pub struct FixedSizeVariantArray<A, T>(A, std::marker::PhantomData<T>)
2251where
2252 A: AsRef<[T]>,
2253 T: FixedSizeVariantType;
2254
2255impl<A: AsRef<[T]>, T: FixedSizeVariantType> From<A> for FixedSizeVariantArray<A, T> {
2256 fn from(array: A) -> Self {
2257 FixedSizeVariantArray(array, std::marker::PhantomData)
2258 }
2259}
2260
2261impl<A: AsRef<[T]>, T: FixedSizeVariantType> FixedSizeVariantArray<A, T> {
2262 pub fn into_inner(self) -> A {
2263 self.0
2264 }
2265}
2266
2267impl<A: AsRef<[T]>, T: FixedSizeVariantType> std::ops::Deref for FixedSizeVariantArray<A, T> {
2268 type Target = A;
2269
2270 #[inline]
2271 fn deref(&self) -> &Self::Target {
2272 &self.0
2273 }
2274}
2275
2276impl<A: AsRef<[T]>, T: FixedSizeVariantType> std::ops::DerefMut for FixedSizeVariantArray<A, T> {
2277 #[inline]
2278 fn deref_mut(&mut self) -> &mut Self::Target {
2279 &mut self.0
2280 }
2281}
2282
2283impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsRef<A> for FixedSizeVariantArray<A, T> {
2284 #[inline]
2285 fn as_ref(&self) -> &A {
2286 &self.0
2287 }
2288}
2289
2290impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsMut<A> for FixedSizeVariantArray<A, T> {
2291 #[inline]
2292 fn as_mut(&mut self) -> &mut A {
2293 &mut self.0
2294 }
2295}
2296
2297impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsRef<[T]> for FixedSizeVariantArray<A, T> {
2298 #[inline]
2299 fn as_ref(&self) -> &[T] {
2300 self.0.as_ref()
2301 }
2302}
2303
2304impl<A: AsRef<[T]> + AsMut<[T]>, T: FixedSizeVariantType> AsMut<[T]>
2305 for FixedSizeVariantArray<A, T>
2306{
2307 #[inline]
2308 fn as_mut(&mut self) -> &mut [T] {
2309 self.0.as_mut()
2310 }
2311}
2312
2313impl<A: AsRef<[T]>, T: FixedSizeVariantType> StaticVariantType for FixedSizeVariantArray<A, T> {
2314 fn static_variant_type() -> Cow<'static, VariantTy> {
2315 <[T]>::static_variant_type()
2316 }
2317}
2318
2319impl<A: AsRef<[T]> + for<'a> From<&'a [T]>, T: FixedSizeVariantType> FromVariant
2320 for FixedSizeVariantArray<A, T>
2321{
2322 fn from_variant(variant: &Variant) -> Option<Self> {
2323 Some(FixedSizeVariantArray(
2324 A::from(variant.fixed_array::<T>().ok()?),
2325 std::marker::PhantomData,
2326 ))
2327 }
2328}
2329
2330impl<A: AsRef<[T]>, T: FixedSizeVariantType> ToVariant for FixedSizeVariantArray<A, T> {
2331 fn to_variant(&self) -> Variant {
2332 Variant::array_from_fixed_array(self.0.as_ref())
2333 }
2334}
2335
2336impl<A: AsRef<[T]> + 'static, T: FixedSizeVariantType> From<FixedSizeVariantArray<A, T>>
2337 for Variant
2338{
2339 #[doc(alias = "g_variant_new_from_data")]
2340 fn from(a: FixedSizeVariantArray<A, T>) -> Self {
2341 unsafe {
2342 let data = Box::new(a.0);
2343 let (data_ptr, len) = {
2344 let data = (*data).as_ref();
2345 (data.as_ptr(), mem::size_of_val(data))
2346 };
2347
2348 unsafe extern "C" fn free_data<A: AsRef<[T]>, T: FixedSizeVariantType>(
2349 ptr: ffi::gpointer,
2350 ) {
2351 unsafe {
2352 let _ = Box::from_raw(ptr as *mut A);
2353 }
2354 }
2355
2356 from_glib_none(ffi::g_variant_new_from_data(
2357 T::static_variant_type().to_glib_none().0,
2358 data_ptr as ffi::gconstpointer,
2359 len,
2360 false.into_glib(),
2361 Some(free_data::<A, T>),
2362 Box::into_raw(data) as ffi::gpointer,
2363 ))
2364 }
2365 }
2366}
2367
2368#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2370pub struct Handle(pub i32);
2371
2372impl From<i32> for Handle {
2373 fn from(v: i32) -> Self {
2374 Handle(v)
2375 }
2376}
2377
2378impl From<Handle> for i32 {
2379 fn from(v: Handle) -> Self {
2380 v.0
2381 }
2382}
2383
2384impl StaticVariantType for Handle {
2385 fn static_variant_type() -> Cow<'static, VariantTy> {
2386 Cow::Borrowed(VariantTy::HANDLE)
2387 }
2388}
2389
2390impl ToVariant for Handle {
2391 fn to_variant(&self) -> Variant {
2392 unsafe { from_glib_none(ffi::g_variant_new_handle(self.0)) }
2393 }
2394}
2395
2396impl From<Handle> for Variant {
2397 #[inline]
2398 fn from(h: Handle) -> Self {
2399 h.to_variant()
2400 }
2401}
2402
2403impl FromVariant for Handle {
2404 fn from_variant(variant: &Variant) -> Option<Self> {
2405 unsafe {
2406 if variant.is::<Self>() {
2407 Some(Handle(ffi::g_variant_get_handle(variant.to_glib_none().0)))
2408 } else {
2409 None
2410 }
2411 }
2412 }
2413}
2414
2415#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2419pub struct ObjectPath(String);
2420
2421impl ObjectPath {
2422 pub fn as_str(&self) -> &str {
2423 &self.0
2424 }
2425}
2426
2427impl Display for ObjectPath {
2428 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2429 self.0.fmt(f)
2430 }
2431}
2432
2433impl std::ops::Deref for ObjectPath {
2434 type Target = str;
2435
2436 #[inline]
2437 fn deref(&self) -> &Self::Target {
2438 &self.0
2439 }
2440}
2441
2442impl TryFrom<String> for ObjectPath {
2443 type Error = crate::BoolError;
2444
2445 fn try_from(v: String) -> Result<Self, Self::Error> {
2446 if !Variant::is_object_path(&v) {
2447 return Err(bool_error!("Invalid object path"));
2448 }
2449
2450 Ok(ObjectPath(v))
2451 }
2452}
2453
2454impl<'a> TryFrom<&'a str> for ObjectPath {
2455 type Error = crate::BoolError;
2456
2457 fn try_from(v: &'a str) -> Result<Self, Self::Error> {
2458 ObjectPath::try_from(String::from(v))
2459 }
2460}
2461
2462impl From<ObjectPath> for String {
2463 fn from(v: ObjectPath) -> Self {
2464 v.0
2465 }
2466}
2467
2468impl StaticVariantType for ObjectPath {
2469 fn static_variant_type() -> Cow<'static, VariantTy> {
2470 Cow::Borrowed(VariantTy::OBJECT_PATH)
2471 }
2472}
2473
2474impl ToVariant for ObjectPath {
2475 fn to_variant(&self) -> Variant {
2476 unsafe { from_glib_none(ffi::g_variant_new_object_path(self.0.to_glib_none().0)) }
2477 }
2478}
2479
2480impl From<ObjectPath> for Variant {
2481 #[inline]
2482 fn from(p: ObjectPath) -> Self {
2483 let mut s = p.0;
2484 s.push('\0');
2485 unsafe { Self::from_data_trusted::<ObjectPath, _>(s) }
2486 }
2487}
2488
2489impl FromVariant for ObjectPath {
2490 #[allow(unused_unsafe)]
2491 fn from_variant(variant: &Variant) -> Option<Self> {
2492 unsafe {
2493 if variant.is::<Self>() {
2494 Some(ObjectPath(String::from(variant.str().unwrap())))
2495 } else {
2496 None
2497 }
2498 }
2499 }
2500}
2501
2502#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2506pub struct Signature(String);
2507
2508impl Signature {
2509 pub fn as_str(&self) -> &str {
2510 &self.0
2511 }
2512}
2513
2514impl std::ops::Deref for Signature {
2515 type Target = str;
2516
2517 #[inline]
2518 fn deref(&self) -> &Self::Target {
2519 &self.0
2520 }
2521}
2522
2523impl TryFrom<String> for Signature {
2524 type Error = crate::BoolError;
2525
2526 fn try_from(v: String) -> Result<Self, Self::Error> {
2527 if !Variant::is_signature(&v) {
2528 return Err(bool_error!("Invalid signature"));
2529 }
2530
2531 Ok(Signature(v))
2532 }
2533}
2534
2535impl<'a> TryFrom<&'a str> for Signature {
2536 type Error = crate::BoolError;
2537
2538 fn try_from(v: &'a str) -> Result<Self, Self::Error> {
2539 Signature::try_from(String::from(v))
2540 }
2541}
2542
2543impl From<Signature> for String {
2544 fn from(v: Signature) -> Self {
2545 v.0
2546 }
2547}
2548
2549impl StaticVariantType for Signature {
2550 fn static_variant_type() -> Cow<'static, VariantTy> {
2551 Cow::Borrowed(VariantTy::SIGNATURE)
2552 }
2553}
2554
2555impl ToVariant for Signature {
2556 fn to_variant(&self) -> Variant {
2557 unsafe { from_glib_none(ffi::g_variant_new_signature(self.0.to_glib_none().0)) }
2558 }
2559}
2560
2561impl From<Signature> for Variant {
2562 #[inline]
2563 fn from(s: Signature) -> Self {
2564 let mut s = s.0;
2565 s.push('\0');
2566 unsafe { Self::from_data_trusted::<Signature, _>(s) }
2567 }
2568}
2569
2570impl FromVariant for Signature {
2571 #[allow(unused_unsafe)]
2572 fn from_variant(variant: &Variant) -> Option<Self> {
2573 unsafe {
2574 if variant.is::<Self>() {
2575 Some(Signature(String::from(variant.str().unwrap())))
2576 } else {
2577 None
2578 }
2579 }
2580 }
2581}
2582
2583#[cfg(test)]
2584mod tests {
2585 use std::collections::{HashMap, HashSet};
2586
2587 use super::*;
2588
2589 macro_rules! unsigned {
2590 ($name:ident, $ty:ident) => {
2591 #[test]
2592 fn $name() {
2593 let mut n = $ty::MAX;
2594 while n > 0 {
2595 let v = n.to_variant();
2596 assert_eq!(v.get(), Some(n));
2597 n /= 2;
2598 }
2599 }
2600 };
2601 }
2602
2603 macro_rules! signed {
2604 ($name:ident, $ty:ident) => {
2605 #[test]
2606 fn $name() {
2607 let mut n = $ty::MAX;
2608 while n > 0 {
2609 let v = n.to_variant();
2610 assert_eq!(v.get(), Some(n));
2611 let v = (-n).to_variant();
2612 assert_eq!(v.get(), Some(-n));
2613 n /= 2;
2614 }
2615 }
2616 };
2617 }
2618
2619 unsigned!(test_u8, u8);
2620 unsigned!(test_u16, u16);
2621 unsigned!(test_u32, u32);
2622 unsigned!(test_u64, u64);
2623 signed!(test_i16, i16);
2624 signed!(test_i32, i32);
2625 signed!(test_i64, i64);
2626
2627 #[test]
2628 fn test_str() {
2629 let s = "this is a test";
2630 let v = s.to_variant();
2631 assert_eq!(v.str(), Some(s));
2632 assert_eq!(42u32.to_variant().str(), None);
2633 }
2634
2635 #[test]
2636 fn test_fixed_array() {
2637 let b = b"this is a test";
2638 let v = Variant::array_from_fixed_array(&b[..]);
2639 assert_eq!(v.type_().as_str(), "ay");
2640 assert_eq!(v.fixed_array::<u8>().unwrap(), b);
2641 assert!(42u32.to_variant().fixed_array::<u8>().is_err());
2642
2643 let b = [1u32, 10u32, 100u32];
2644 let v = Variant::array_from_fixed_array(&b);
2645 assert_eq!(v.type_().as_str(), "au");
2646 assert_eq!(v.fixed_array::<u32>().unwrap(), b);
2647 assert!(v.fixed_array::<u8>().is_err());
2648
2649 let b = [true, false, true];
2650 let v = Variant::array_from_fixed_array(&b);
2651 assert_eq!(v.type_().as_str(), "ab");
2652 assert_eq!(v.fixed_array::<bool>().unwrap(), b);
2653 assert!(v.fixed_array::<u8>().is_err());
2654
2655 let b = [1.0f64, 2.0f64, 3.0f64];
2656 let v = Variant::array_from_fixed_array(&b);
2657 assert_eq!(v.type_().as_str(), "ad");
2658 #[allow(clippy::float_cmp)]
2659 {
2660 assert_eq!(v.fixed_array::<f64>().unwrap(), b);
2661 }
2662 assert!(v.fixed_array::<u64>().is_err());
2663 }
2664
2665 #[test]
2666 fn test_fixed_variant_array() {
2667 let b = FixedSizeVariantArray::from(&b"this is a test"[..]);
2668 let v = b.to_variant();
2669 assert_eq!(v.type_().as_str(), "ay");
2670 assert_eq!(
2671 &*v.get::<FixedSizeVariantArray<Vec<u8>, u8>>().unwrap(),
2672 &*b
2673 );
2674
2675 let b = FixedSizeVariantArray::from(vec![1i32, 2, 3]);
2676 let v = b.to_variant();
2677 assert_eq!(v.type_().as_str(), "ai");
2678 assert_eq!(v.get::<FixedSizeVariantArray<Vec<i32>, i32>>().unwrap(), b);
2679 }
2680
2681 #[test]
2682 fn test_string() {
2683 let s = String::from("this is a test");
2684 let v = s.to_variant();
2685 assert_eq!(v.get(), Some(s));
2686 assert_eq!(v.normal_form(), v);
2687 }
2688
2689 #[test]
2690 fn test_eq() {
2691 let v1 = "this is a test".to_variant();
2692 let v2 = "this is a test".to_variant();
2693 let v3 = "test".to_variant();
2694 assert_eq!(v1, v2);
2695 assert_ne!(v1, v3);
2696 }
2697
2698 #[test]
2699 fn test_hash() {
2700 let v1 = "this is a test".to_variant();
2701 let v2 = "this is a test".to_variant();
2702 let v3 = "test".to_variant();
2703 let mut set = HashSet::new();
2704 set.insert(v1);
2705 assert!(set.contains(&v2));
2706 assert!(!set.contains(&v3));
2707
2708 assert_eq!(
2709 <HashMap<&str, (&str, u8, u32)>>::static_variant_type().as_str(),
2710 "a{s(syu)}"
2711 );
2712 }
2713
2714 #[test]
2715 fn test_array() {
2716 assert_eq!(<Vec<&str>>::static_variant_type().as_str(), "as");
2717 assert_eq!(
2718 <Vec<(&str, u8, u32)>>::static_variant_type().as_str(),
2719 "a(syu)"
2720 );
2721 let a = ["foo", "bar", "baz"].to_variant();
2722 assert_eq!(a.normal_form(), a);
2723 assert_eq!(a.array_iter_str().unwrap().len(), 3);
2724 let o = 0u32.to_variant();
2725 assert!(o.array_iter_str().is_err());
2726 }
2727
2728 #[test]
2729 fn test_array_from_iter() {
2730 let a = Variant::array_from_iter::<String>(
2731 ["foo", "bar", "baz"].into_iter().map(|s| s.to_variant()),
2732 );
2733 assert_eq!(a.type_().as_str(), "as");
2734 assert_eq!(a.n_children(), 3);
2735
2736 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
2737 assert_eq!(a.try_child_get::<String>(1), Ok(Some(String::from("bar"))));
2738 assert_eq!(a.try_child_get::<String>(2), Ok(Some(String::from("baz"))));
2739 }
2740
2741 #[test]
2742 fn test_array_collect() {
2743 let a = ["foo", "bar", "baz"].into_iter().collect::<Variant>();
2744 assert_eq!(a.type_().as_str(), "as");
2745 assert_eq!(a.n_children(), 3);
2746
2747 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
2748 assert_eq!(a.try_child_get::<String>(1), Ok(Some(String::from("bar"))));
2749 assert_eq!(a.try_child_get::<String>(2), Ok(Some(String::from("baz"))));
2750 }
2751
2752 #[test]
2753 fn test_tuple() {
2754 assert_eq!(<(&str, u32)>::static_variant_type().as_str(), "(su)");
2755 assert_eq!(<(&str, u8, u32)>::static_variant_type().as_str(), "(syu)");
2756 let a = ("test", 1u8, 2u32).to_variant();
2757 assert_eq!(a.normal_form(), a);
2758 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("test"))));
2759 assert_eq!(a.try_child_get::<u8>(1), Ok(Some(1u8)));
2760 assert_eq!(a.try_child_get::<u32>(2), Ok(Some(2u32)));
2761 assert_eq!(
2762 a.try_get::<(String, u8, u32)>(),
2763 Ok((String::from("test"), 1u8, 2u32))
2764 );
2765 }
2766
2767 #[test]
2768 fn test_tuple_from_iter() {
2769 let a = Variant::tuple_from_iter(["foo".to_variant(), 1u8.to_variant(), 2i32.to_variant()]);
2770 assert_eq!(a.type_().as_str(), "(syi)");
2771 assert_eq!(a.n_children(), 3);
2772
2773 assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
2774 assert_eq!(a.try_child_get::<u8>(1), Ok(Some(1u8)));
2775 assert_eq!(a.try_child_get::<i32>(2), Ok(Some(2i32)));
2776 }
2777
2778 #[test]
2779 fn test_empty() {
2780 assert_eq!(<()>::static_variant_type().as_str(), "()");
2781 let a = ().to_variant();
2782 assert_eq!(a.type_().as_str(), "()");
2783 assert_eq!(a.get::<()>(), Some(()));
2784 }
2785
2786 #[test]
2787 fn test_maybe() {
2788 assert!(<Option<()>>::static_variant_type().is_maybe());
2789 let m1 = Some(()).to_variant();
2790 assert_eq!(m1.type_().as_str(), "m()");
2791
2792 assert_eq!(m1.get::<Option<()>>(), Some(Some(())));
2793 assert!(m1.as_maybe().is_some());
2794
2795 let m2 = None::<()>.to_variant();
2796 assert!(m2.as_maybe().is_none());
2797 }
2798
2799 #[test]
2800 fn test_btreemap() {
2801 assert_eq!(
2802 <BTreeMap<String, u32>>::static_variant_type().as_str(),
2803 "a{su}"
2804 );
2805 let mut m = BTreeMap::new();
2807 let total = 20;
2808 for n in 0..total {
2809 let k = format!("v{n:04}");
2810 m.insert(k, n as u32);
2811 }
2812 let v = m.to_variant();
2813 let n = v.n_children();
2814 assert_eq!(total, n);
2815 for n in 0..total {
2816 let child = v
2817 .try_child_get::<DictEntry<String, u32>>(n)
2818 .unwrap()
2819 .unwrap();
2820 assert_eq!(*child.value(), n as u32);
2821 }
2822
2823 assert_eq!(BTreeMap::from_variant(&v).unwrap(), m);
2824 }
2825
2826 #[test]
2827 fn test_get() -> Result<(), Box<dyn std::error::Error>> {
2828 let u = 42u32.to_variant();
2829 assert!(u.get::<i32>().is_none());
2830 assert_eq!(u.get::<u32>().unwrap(), 42);
2831 assert!(u.try_get::<i32>().is_err());
2832 assert_eq!(u.try_get::<u32>()?, 42);
2834 Ok(())
2835 }
2836
2837 #[test]
2838 fn test_byteswap() {
2839 let u = 42u32.to_variant();
2840 assert_eq!(u.byteswap().get::<u32>().unwrap(), 704643072u32);
2841 assert_eq!(u.byteswap().byteswap().get::<u32>().unwrap(), 42u32);
2842 }
2843
2844 #[test]
2845 fn test_try_child() {
2846 let a = ["foo"].to_variant();
2847 assert!(a.try_child_value(0).is_some());
2848 assert_eq!(a.try_child_get::<String>(0).unwrap().unwrap(), "foo");
2849 assert_eq!(a.child_get::<String>(0), "foo");
2850 assert!(a.try_child_get::<u32>(0).is_err());
2851 assert!(a.try_child_value(1).is_none());
2852 assert!(a.try_child_get::<String>(1).unwrap().is_none());
2853 let u = 42u32.to_variant();
2854 assert!(u.try_child_value(0).is_none());
2855 assert!(u.try_child_get::<String>(0).unwrap().is_none());
2856 }
2857
2858 #[test]
2859 fn test_serialize() {
2860 let a = ("test", 1u8, 2u32).to_variant();
2861
2862 let bytes = a.data_as_bytes();
2863 let data = a.data();
2864 let len = a.size();
2865 assert_eq!(bytes.len(), len);
2866 assert_eq!(data.len(), len);
2867
2868 let mut store_data = vec![0u8; len];
2869 assert_eq!(a.store(&mut store_data).unwrap(), len);
2870
2871 assert_eq!(&bytes, data);
2872 assert_eq!(&store_data, data);
2873
2874 let b = Variant::from_data::<(String, u8, u32), _>(store_data);
2875 assert_eq!(a, b);
2876
2877 let c = Variant::from_bytes::<(String, u8, u32)>(&bytes);
2878 assert_eq!(a, c);
2879 }
2880
2881 #[test]
2882 fn test_print_parse() {
2883 let a = ("test", 1u8, 2u32).to_variant();
2884
2885 let a2 = Variant::parse(Some(a.type_()), &a.print(false)).unwrap();
2886 assert_eq!(a, a2);
2887
2888 let a3: Variant = a.to_string().parse().unwrap();
2889 assert_eq!(a, a3);
2890 }
2891
2892 #[cfg(any(unix, windows))]
2893 #[test]
2894 fn test_paths() {
2895 use std::path::PathBuf;
2896
2897 let path = PathBuf::from("foo");
2898 let v = path.to_variant();
2899 assert_eq!(PathBuf::from_variant(&v), Some(path));
2900 }
2901
2902 #[test]
2903 fn test_regression_from_variant_panics() {
2904 let variant = "text".to_variant();
2905 let hashmap: Option<HashMap<u64, u64>> = FromVariant::from_variant(&variant);
2906 assert!(hashmap.is_none());
2907
2908 let variant = HashMap::<u64, u64>::new().to_variant();
2909 let hashmap: Option<HashMap<u64, u64>> = FromVariant::from_variant(&variant);
2910 assert!(hashmap.is_some());
2911 }
2912}