Skip to main content

glib/
variant.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3// rustdoc-stripper-ignore-next
4//! `Variant` binding and helper traits.
5//!
6//! [`Variant`](struct.Variant.html) is an immutable dynamically-typed generic
7//! container. Its type and value are defined at construction and never change.
8//!
9//! `Variant` types are described by [`VariantType`](../struct.VariantType.html)
10//! "type strings".
11//!
12//! `GVariant` supports arbitrarily complex types built from primitives like integers, floating point
13//! numbers, strings, arrays, tuples and dictionaries. See [`ToVariant#foreign-impls`] for
14//! a full list of supported types. You may also implement [`ToVariant`] and [`FromVariant`]
15//! manually, or derive them using the [`Variant`](derive@crate::Variant) derive macro.
16//!
17//! # Examples
18//!
19//! ```
20//! use glib::prelude::*; // or `use gtk::prelude::*;`
21//! use glib::variant::{Variant, FromVariant};
22//! use std::collections::HashMap;
23//!
24//! // Using the `ToVariant` trait.
25//! let num = 10.to_variant();
26//!
27//! // `is` tests the type of the value.
28//! assert!(num.is::<i32>());
29//!
30//! // `get` tries to extract the value.
31//! assert_eq!(num.get::<i32>(), Some(10));
32//! assert_eq!(num.get::<u32>(), None);
33//!
34//! // `get_str` tries to borrow a string slice.
35//! let hello = "Hello!".to_variant();
36//! assert_eq!(hello.str(), Some("Hello!"));
37//! assert_eq!(num.str(), None);
38//!
39//! // `fixed_array` tries to borrow a fixed size array (u8, bool, i16, etc.),
40//! // rather than creating a deep copy which would be expensive for
41//! // nontrivially sized arrays of fixed size elements.
42//! // The test data here is the zstd compression header, which
43//! // stands in for arbitrary binary data (e.g. not UTF-8).
44//! let bufdata = b"\xFD\x2F\xB5\x28";
45//! let bufv = glib::Variant::array_from_fixed_array(&bufdata[..]);
46//! assert_eq!(bufv.fixed_array::<u8>().unwrap(), bufdata);
47//! assert!(num.fixed_array::<u8>().is_err());
48//!
49//! // Variant carrying a Variant
50//! let variant = Variant::from_variant(&hello);
51//! let variant = variant.as_variant().unwrap();
52//! assert_eq!(variant.str(), Some("Hello!"));
53//!
54//! // Variant carrying an array
55//! let array = ["Hello", "there!"];
56//! let variant = array.into_iter().collect::<Variant>();
57//! assert_eq!(variant.n_children(), 2);
58//! assert_eq!(variant.child_value(0).str(), Some("Hello"));
59//! assert_eq!(variant.child_value(1).str(), Some("there!"));
60//!
61//! // You can also convert from and to a Vec
62//! let variant = vec!["Hello", "there!"].to_variant();
63//! assert_eq!(variant.n_children(), 2);
64//! let vec = <Vec<String>>::from_variant(&variant).unwrap();
65//! assert_eq!(vec[0], "Hello");
66//!
67//! // Conversion to and from HashMap and BTreeMap is also possible
68//! let mut map: HashMap<u16, &str> = HashMap::new();
69//! map.insert(1, "hi");
70//! map.insert(2, "there");
71//! let variant = map.to_variant();
72//! assert_eq!(variant.n_children(), 2);
73//! let map: HashMap<u16, String> = HashMap::from_variant(&variant).unwrap();
74//! assert_eq!(map[&1], "hi");
75//! assert_eq!(map[&2], "there");
76//!
77//! // And conversion to and from tuples.
78//! let variant = ("hello", 42u16, vec![ "there", "you" ],).to_variant();
79//! assert_eq!(variant.n_children(), 3);
80//! assert_eq!(variant.type_().as_str(), "(sqas)");
81//! let tuple = <(String, u16, Vec<String>)>::from_variant(&variant).unwrap();
82//! assert_eq!(tuple.0, "hello");
83//! assert_eq!(tuple.1, 42);
84//! assert_eq!(tuple.2, &[ "there", "you"]);
85//!
86//! // `Option` is supported as well, through maybe types
87//! let variant = Some("hello").to_variant();
88//! assert_eq!(variant.n_children(), 1);
89//! let mut s = <Option<String>>::from_variant(&variant).unwrap();
90//! assert_eq!(s.unwrap(), "hello");
91//! s = None;
92//! let variant = s.to_variant();
93//! assert_eq!(variant.n_children(), 0);
94//! let s = <Option<String>>::from_variant(&variant).unwrap();
95//! assert!(s.is_none());
96//!
97//! // Paths may be converted, too. Please note the portability warning above!
98//! use std::path::{Path, PathBuf};
99//! let path = Path::new("foo/bar");
100//! let path_variant = path.to_variant();
101//! assert_eq!(PathBuf::from_variant(&path_variant).as_deref(), Some(path));
102//! ```
103
104use 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    // rustdoc-stripper-ignore-next
121    /// A generic immutable value capable of carrying various types.
122    ///
123    /// See the [module documentation](index.html) for more details.
124    // rustdoc-stripper-ignore-next-stop
125    ///  the one referring to the
126    /// dictionary.
127    ///
128    /// If calls are made to start accessing the other values then
129    /// `GVariant` instances will exist for those values only for as long
130    /// as they are in use (ie: until you call `GLib::Variant::unref()`).  The
131    /// type information is shared.  The serialized data and the buffer
132    /// management structure for that serialized data is shared by the
133    /// child.
134    ///
135    /// ## Summary
136    ///
137    /// To put the entire example together, for our dictionary mapping
138    /// strings to variants (with two entries, as given above), we are
139    /// using 91 bytes of memory for type information, 29 bytes of memory
140    /// for the serialized data, 16 bytes for buffer management and 24
141    /// bytes for the `GVariant` instance, or a total of 160 bytes, plus
142    /// allocation overhead.  If we were to use [`child_value()`][Self::child_value()]
143    /// to access the two dictionary entries, we would use an additional 48
144    /// bytes.  If we were to have other dictionaries of the same type, we
145    /// would use more memory for the serialized data and buffer
146    /// management for those dictionaries, but the type information would
147    /// be shared.
148    // rustdoc-stripper-ignore-next-stop
149    ///  the one referring to the
150    /// dictionary.
151    ///
152    /// If calls are made to start accessing the other values then
153    /// `GVariant` instances will exist for those values only for as long
154    /// as they are in use (ie: until you call `GLib::Variant::unref()`).  The
155    /// type information is shared.  The serialized data and the buffer
156    /// management structure for that serialized data is shared by the
157    /// child.
158    ///
159    /// ## Summary
160    ///
161    /// To put the entire example together, for our dictionary mapping
162    /// strings to variants (with two entries, as given above), we are
163    /// using 91 bytes of memory for type information, 29 bytes of memory
164    /// for the serialized data, 16 bytes for buffer management and 24
165    /// bytes for the `GVariant` instance, or a total of 160 bytes, plus
166    /// allocation overhead.  If we were to use [`child_value()`][Self::child_value()]
167    /// to access the two dictionary entries, we would use an additional 48
168    /// bytes.  If we were to have other dictionaries of the same type, we
169    /// would use more memory for the serialized data and buffer
170    /// management for those dictionaries, but the type information would
171    /// be shared.
172    #[doc(alias = "GVariant")]
173    pub struct Variant(Shared<ffi::GVariant>);
174
175    match fn {
176        ref => |ptr| ffi::g_variant_ref_sink(ptr),
177        unref => |ptr| ffi::g_variant_unref(ptr),
178    }
179}
180
181impl StaticType for Variant {
182    #[inline]
183    fn static_type() -> Type {
184        Type::VARIANT
185    }
186}
187
188#[doc(hidden)]
189impl crate::value::ValueType for Variant {
190    type Type = Variant;
191}
192
193#[doc(hidden)]
194impl crate::value::ValueTypeOptional for Variant {}
195
196#[doc(hidden)]
197unsafe impl<'a> crate::value::FromValue<'a> for Variant {
198    type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
199
200    unsafe fn from_value(value: &'a crate::Value) -> Self {
201        unsafe {
202            let ptr = gobject_ffi::g_value_dup_variant(value.to_glib_none().0);
203            debug_assert!(!ptr.is_null());
204            from_glib_full(ptr)
205        }
206    }
207}
208
209#[doc(hidden)]
210impl crate::value::ToValue for Variant {
211    fn to_value(&self) -> crate::Value {
212        unsafe {
213            let mut value = crate::Value::from_type_unchecked(Variant::static_type());
214            gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, self.to_glib_full());
215            value
216        }
217    }
218
219    fn value_type(&self) -> crate::Type {
220        Variant::static_type()
221    }
222}
223
224#[doc(hidden)]
225impl From<Variant> for crate::Value {
226    #[inline]
227    fn from(v: Variant) -> Self {
228        unsafe {
229            let mut value = crate::Value::from_type_unchecked(Variant::static_type());
230            gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, v.into_glib_ptr());
231            value
232        }
233    }
234}
235
236#[doc(hidden)]
237impl crate::value::ToValueOptional for Variant {
238    fn to_value_optional(s: Option<&Self>) -> crate::Value {
239        let mut value = crate::Value::for_value_type::<Self>();
240        unsafe {
241            gobject_ffi::g_value_take_variant(value.to_glib_none_mut().0, s.to_glib_full());
242        }
243
244        value
245    }
246}
247
248// rustdoc-stripper-ignore-next
249/// An error returned from the [`try_get`](struct.Variant.html#method.try_get) function
250/// on a [`Variant`](struct.Variant.html) when the expected type does not match the actual type.
251#[derive(Clone, PartialEq, Eq, Debug)]
252pub struct VariantTypeMismatchError {
253    pub actual: VariantType,
254    pub expected: VariantType,
255}
256
257impl VariantTypeMismatchError {
258    pub fn new(actual: VariantType, expected: VariantType) -> Self {
259        Self { actual, expected }
260    }
261}
262
263impl fmt::Display for VariantTypeMismatchError {
264    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265        write!(
266            f,
267            "Type mismatch: Expected '{}' got '{}'",
268            self.expected, self.actual
269        )
270    }
271}
272
273impl std::error::Error for VariantTypeMismatchError {}
274
275impl Variant {
276    // rustdoc-stripper-ignore-next
277    /// Returns the type of the value.
278    // rustdoc-stripper-ignore-next-stop
279    /// Determines the type of @self.
280    ///
281    /// The return value is valid for the lifetime of @self and must not
282    /// be freed.
283    ///
284    /// # Returns
285    ///
286    /// a #GVariantType
287    // rustdoc-stripper-ignore-next-stop
288    /// Determines the type of @self.
289    ///
290    /// The return value is valid for the lifetime of @self and must not
291    /// be freed.
292    ///
293    /// # Returns
294    ///
295    /// a #GVariantType
296    #[doc(alias = "g_variant_get_type")]
297    pub fn type_(&self) -> &VariantTy {
298        unsafe { VariantTy::from_ptr(ffi::g_variant_get_type(self.to_glib_none().0)) }
299    }
300
301    // rustdoc-stripper-ignore-next
302    /// Returns `true` if the type of the value corresponds to `T`.
303    #[inline]
304    #[doc(alias = "g_variant_is_of_type")]
305    pub fn is<T: StaticVariantType>(&self) -> bool {
306        self.is_type(&T::static_variant_type())
307    }
308
309    // rustdoc-stripper-ignore-next
310    /// Returns `true` if the type of the value corresponds to `type_`.
311    ///
312    /// This is equivalent to [`self.type_().is_subtype_of(type_)`](VariantTy::is_subtype_of).
313    #[inline]
314    #[doc(alias = "g_variant_is_of_type")]
315    pub fn is_type(&self, type_: &VariantTy) -> bool {
316        unsafe {
317            from_glib(ffi::g_variant_is_of_type(
318                self.to_glib_none().0,
319                type_.to_glib_none().0,
320            ))
321        }
322    }
323
324    // rustdoc-stripper-ignore-next
325    /// Returns the classification of the variant.
326    // rustdoc-stripper-ignore-next-stop
327    /// Classifies @self according to its top-level type.
328    ///
329    /// # Returns
330    ///
331    /// the #GVariantClass of @self
332    // rustdoc-stripper-ignore-next-stop
333    /// Classifies @self according to its top-level type.
334    ///
335    /// # Returns
336    ///
337    /// the #GVariantClass of @self
338    #[doc(alias = "g_variant_classify")]
339    pub fn classify(&self) -> crate::VariantClass {
340        unsafe { from_glib(ffi::g_variant_classify(self.to_glib_none().0)) }
341    }
342
343    // rustdoc-stripper-ignore-next
344    /// Tries to extract a value of type `T`.
345    ///
346    /// Returns `Some` if `T` matches the variant's type.
347    // rustdoc-stripper-ignore-next-stop
348    /// Deconstructs a #GVariant instance.
349    ///
350    /// Think of this function as an analogue to scanf().
351    ///
352    /// The arguments that are expected by this function are entirely
353    /// determined by @format_string.  @format_string also restricts the
354    /// permissible types of @self.  It is an error to give a value with
355    /// an incompatible type.  See the section on
356    /// [GVariant format strings](gvariant-format-strings.html).
357    /// Please note that the syntax of the format string is very likely to be
358    /// extended in the future.
359    ///
360    /// @format_string determines the C types that are used for unpacking
361    /// the values and also determines if the values are copied or borrowed,
362    /// see the section on
363    /// [`GVariant` format strings](gvariant-format-strings.html#pointers).
364    /// ## `format_string`
365    /// a #GVariant format string
366    // rustdoc-stripper-ignore-next-stop
367    /// Deconstructs a #GVariant instance.
368    ///
369    /// Think of this function as an analogue to scanf().
370    ///
371    /// The arguments that are expected by this function are entirely
372    /// determined by @format_string.  @format_string also restricts the
373    /// permissible types of @self.  It is an error to give a value with
374    /// an incompatible type.  See the section on
375    /// [GVariant format strings](gvariant-format-strings.html).
376    /// Please note that the syntax of the format string is very likely to be
377    /// extended in the future.
378    ///
379    /// @format_string determines the C types that are used for unpacking
380    /// the values and also determines if the values are copied or borrowed,
381    /// see the section on
382    /// [`GVariant` format strings](gvariant-format-strings.html#pointers).
383    /// ## `format_string`
384    /// a #GVariant format string
385    #[inline]
386    pub fn get<T: FromVariant>(&self) -> Option<T> {
387        T::from_variant(self)
388    }
389
390    // rustdoc-stripper-ignore-next
391    /// Tries to extract a value of type `T`.
392    pub fn try_get<T: FromVariant>(&self) -> Result<T, VariantTypeMismatchError> {
393        self.get().ok_or_else(|| {
394            VariantTypeMismatchError::new(
395                self.type_().to_owned(),
396                T::static_variant_type().into_owned(),
397            )
398        })
399    }
400
401    // rustdoc-stripper-ignore-next
402    /// Boxes value.
403    #[inline]
404    pub fn from_variant(value: &Variant) -> Self {
405        unsafe { from_glib_none(ffi::g_variant_new_variant(value.to_glib_none().0)) }
406    }
407
408    // rustdoc-stripper-ignore-next
409    /// Unboxes self.
410    ///
411    /// Returns `Some` if self contains a `Variant`.
412    #[inline]
413    #[doc(alias = "get_variant")]
414    pub fn as_variant(&self) -> Option<Variant> {
415        unsafe { from_glib_full(ffi::g_variant_get_variant(self.to_glib_none().0)) }
416    }
417
418    // rustdoc-stripper-ignore-next
419    /// Reads a child item out of a container `Variant` instance.
420    ///
421    /// # Panics
422    ///
423    /// * if `self` is not a container type.
424    /// * if given `index` is larger than number of children.
425    // rustdoc-stripper-ignore-next-stop
426    /// Reads a child item out of a container #GVariant instance.  This
427    /// includes variants, maybes, arrays, tuples and dictionary
428    /// entries.  It is an error to call this function on any other type of
429    /// #GVariant.
430    ///
431    /// It is an error if @index_ is greater than the number of child items
432    /// in the container.  See g_variant_n_children().
433    ///
434    /// The returned value is never floating.  You should free it with
435    /// g_variant_unref() when you're done with it.
436    ///
437    /// Note that values borrowed from the returned child are not guaranteed to
438    /// still be valid after the child is freed even if you still hold a reference
439    /// to @self, if @self has not been serialized at the time this function is
440    /// called. To avoid this, you can serialize @self by calling
441    /// g_variant_get_data() and optionally ignoring the return value.
442    ///
443    /// There may be implementation specific restrictions on deeply nested values,
444    /// which would result in the unit tuple being returned as the child value,
445    /// instead of further nested children. #GVariant is guaranteed to handle
446    /// nesting up to at least 64 levels.
447    ///
448    /// This function is O(1).
449    /// ## `index_`
450    /// the index of the child to fetch
451    ///
452    /// # Returns
453    ///
454    /// the child at the specified index
455    // rustdoc-stripper-ignore-next-stop
456    /// Reads a child item out of a container #GVariant instance.  This
457    /// includes variants, maybes, arrays, tuples and dictionary
458    /// entries.  It is an error to call this function on any other type of
459    /// #GVariant.
460    ///
461    /// It is an error if @index_ is greater than the number of child items
462    /// in the container.  See g_variant_n_children().
463    ///
464    /// The returned value is never floating.  You should free it with
465    /// g_variant_unref() when you're done with it.
466    ///
467    /// Note that values borrowed from the returned child are not guaranteed to
468    /// still be valid after the child is freed even if you still hold a reference
469    /// to @self, if @self has not been serialized at the time this function is
470    /// called. To avoid this, you can serialize @self by calling
471    /// g_variant_get_data() and optionally ignoring the return value.
472    ///
473    /// There may be implementation specific restrictions on deeply nested values,
474    /// which would result in the unit tuple being returned as the child value,
475    /// instead of further nested children. #GVariant is guaranteed to handle
476    /// nesting up to at least 64 levels.
477    ///
478    /// This function is O(1).
479    /// ## `index_`
480    /// the index of the child to fetch
481    ///
482    /// # Returns
483    ///
484    /// the child at the specified index
485    #[doc(alias = "get_child_value")]
486    #[doc(alias = "g_variant_get_child_value")]
487    #[must_use]
488    pub fn child_value(&self, index: usize) -> Variant {
489        assert!(self.is_container());
490        assert!(index < self.n_children());
491
492        unsafe { from_glib_full(ffi::g_variant_get_child_value(self.to_glib_none().0, index)) }
493    }
494
495    // rustdoc-stripper-ignore-next
496    /// Try to read a child item out of a container `Variant` instance.
497    ///
498    /// It returns `None` if `self` is not a container type or if the given
499    /// `index` is larger than number of children.
500    pub fn try_child_value(&self, index: usize) -> Option<Variant> {
501        if !(self.is_container() && index < self.n_children()) {
502            return None;
503        }
504
505        let v =
506            unsafe { from_glib_full(ffi::g_variant_get_child_value(self.to_glib_none().0, index)) };
507        Some(v)
508    }
509
510    // rustdoc-stripper-ignore-next
511    /// Try to read a child item out of a container `Variant` instance.
512    ///
513    /// It returns `Ok(None)` if `self` is not a container type or if the given
514    /// `index` is larger than number of children.  An error is thrown if the
515    /// type does not match.
516    pub fn try_child_get<T: StaticVariantType + FromVariant>(
517        &self,
518        index: usize,
519    ) -> Result<Option<T>, VariantTypeMismatchError> {
520        // TODO: In the future optimize this by using g_variant_get_child()
521        // directly to avoid allocating a GVariant.
522        self.try_child_value(index).map(|v| v.try_get()).transpose()
523    }
524
525    // rustdoc-stripper-ignore-next
526    /// Read a child item out of a container `Variant` instance.
527    ///
528    /// # Panics
529    ///
530    /// * if `self` is not a container type.
531    /// * if given `index` is larger than number of children.
532    /// * if the expected variant type does not match
533    pub fn child_get<T: StaticVariantType + FromVariant>(&self, index: usize) -> T {
534        // TODO: In the future optimize this by using g_variant_get_child()
535        // directly to avoid allocating a GVariant.
536        self.child_value(index).get().unwrap()
537    }
538
539    // rustdoc-stripper-ignore-next
540    /// Tries to extract a `&str`.
541    ///
542    /// Returns `Some` if the variant has a string type (`s`, `o` or `g` type
543    /// strings).
544    #[doc(alias = "get_str")]
545    #[doc(alias = "g_variant_get_string")]
546    pub fn str(&self) -> Option<&str> {
547        unsafe {
548            match self.type_().as_str() {
549                "s" | "o" | "g" => {
550                    let mut len = 0;
551                    let ptr = ffi::g_variant_get_string(self.to_glib_none().0, &mut len);
552                    if len == 0 {
553                        Some("")
554                    } else {
555                        let ret = str::from_utf8_unchecked(slice::from_raw_parts(
556                            ptr as *const u8,
557                            len as _,
558                        ));
559                        Some(ret)
560                    }
561                }
562                _ => None,
563            }
564        }
565    }
566
567    // rustdoc-stripper-ignore-next
568    /// Tries to extract a `&[T]` from a variant of array type with a suitable element type.
569    ///
570    /// Returns an error if the type is wrong.
571    // rustdoc-stripper-ignore-next-stop
572    /// Provides access to the serialized data for an array of fixed-sized
573    /// items.
574    ///
575    /// @self must be an array with fixed-sized elements.  Numeric types are
576    /// fixed-size, as are tuples containing only other fixed-sized types.
577    ///
578    /// @element_size must be the size of a single element in the array,
579    /// as given by the section on
580    /// [serialized data memory](struct.Variant.html#serialized-data-memory).
581    ///
582    /// In particular, arrays of these fixed-sized types can be interpreted
583    /// as an array of the given C type, with @element_size set to the size
584    /// the appropriate type:
585    ///
586    /// - `G_VARIANT_TYPE_INT16` (etc.): #gint16 (etc.)
587    /// - `G_VARIANT_TYPE_BOOLEAN`: #guchar (not #gboolean!)
588    /// - `G_VARIANT_TYPE_BYTE`: #guint8
589    /// - `G_VARIANT_TYPE_HANDLE`: #guint32
590    /// - `G_VARIANT_TYPE_DOUBLE`: #gdouble
591    ///
592    /// For example, if calling this function for an array of 32-bit integers,
593    /// you might say `sizeof(gint32)`. This value isn't used except for the purpose
594    /// of a double-check that the form of the serialized data matches the caller's
595    /// expectation.
596    ///
597    /// @n_elements, which must be non-[`None`], is set equal to the number of
598    /// items in the array.
599    /// ## `element_size`
600    /// the size of each element
601    ///
602    /// # Returns
603    ///
604    /// a pointer to
605    ///     the fixed array
606    // rustdoc-stripper-ignore-next-stop
607    /// Provides access to the serialized data for an array of fixed-sized
608    /// items.
609    ///
610    /// @self must be an array with fixed-sized elements.  Numeric types are
611    /// fixed-size, as are tuples containing only other fixed-sized types.
612    ///
613    /// @element_size must be the size of a single element in the array,
614    /// as given by the section on
615    /// [serialized data memory](struct.Variant.html#serialized-data-memory).
616    ///
617    /// In particular, arrays of these fixed-sized types can be interpreted
618    /// as an array of the given C type, with @element_size set to the size
619    /// the appropriate type:
620    ///
621    /// - `G_VARIANT_TYPE_INT16` (etc.): #gint16 (etc.)
622    /// - `G_VARIANT_TYPE_BOOLEAN`: #guchar (not #gboolean!)
623    /// - `G_VARIANT_TYPE_BYTE`: #guint8
624    /// - `G_VARIANT_TYPE_HANDLE`: #guint32
625    /// - `G_VARIANT_TYPE_DOUBLE`: #gdouble
626    ///
627    /// For example, if calling this function for an array of 32-bit integers,
628    /// you might say `sizeof(gint32)`. This value isn't used except for the purpose
629    /// of a double-check that the form of the serialized data matches the caller's
630    /// expectation.
631    ///
632    /// @n_elements, which must be non-[`None`], is set equal to the number of
633    /// items in the array.
634    /// ## `element_size`
635    /// the size of each element
636    ///
637    /// # Returns
638    ///
639    /// a pointer to
640    ///     the fixed array
641    #[doc(alias = "g_variant_get_fixed_array")]
642    pub fn fixed_array<T: FixedSizeVariantType>(&self) -> Result<&[T], VariantTypeMismatchError> {
643        unsafe {
644            let expected_ty = T::static_variant_type().as_array();
645            if self.type_() != expected_ty {
646                return Err(VariantTypeMismatchError {
647                    actual: self.type_().to_owned(),
648                    expected: expected_ty.into_owned(),
649                });
650            }
651
652            let mut n_elements = mem::MaybeUninit::uninit();
653            let ptr = ffi::g_variant_get_fixed_array(
654                self.to_glib_none().0,
655                n_elements.as_mut_ptr(),
656                mem::size_of::<T>(),
657            );
658
659            let n_elements = n_elements.assume_init();
660            if n_elements == 0 {
661                Ok(&[])
662            } else {
663                debug_assert!(!ptr.is_null());
664                Ok(slice::from_raw_parts(ptr as *const T, n_elements))
665            }
666        }
667    }
668
669    // rustdoc-stripper-ignore-next
670    /// Creates a new Variant array from children.
671    ///
672    /// # Panics
673    ///
674    /// This function panics if not all variants are of type `T`.
675    #[doc(alias = "g_variant_new_array")]
676    pub fn array_from_iter<T: StaticVariantType>(
677        children: impl IntoIterator<Item = Variant>,
678    ) -> Self {
679        Self::array_from_iter_with_type(&T::static_variant_type(), children)
680    }
681
682    // rustdoc-stripper-ignore-next
683    /// Creates a new Variant array from children with the specified type.
684    ///
685    /// # Panics
686    ///
687    /// This function panics if not all variants are of type `type_`.
688    #[doc(alias = "g_variant_new_array")]
689    pub fn array_from_iter_with_type(
690        type_: &VariantTy,
691        children: impl IntoIterator<Item = impl AsRef<Variant>>,
692    ) -> Self {
693        unsafe {
694            let mut builder = mem::MaybeUninit::uninit();
695            ffi::g_variant_builder_init(builder.as_mut_ptr(), type_.as_array().to_glib_none().0);
696            let mut builder = builder.assume_init();
697            for value in children.into_iter() {
698                let value = value.as_ref();
699                if ffi::g_variant_is_of_type(value.to_glib_none().0, type_.to_glib_none().0)
700                    == ffi::GFALSE
701                {
702                    ffi::g_variant_builder_clear(&mut builder);
703                    assert!(value.is_type(type_));
704                }
705
706                ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
707            }
708            from_glib_none(ffi::g_variant_builder_end(&mut builder))
709        }
710    }
711
712    // rustdoc-stripper-ignore-next
713    /// Creates a new Variant array from a fixed array.
714    #[doc(alias = "g_variant_new_fixed_array")]
715    pub fn array_from_fixed_array<T: FixedSizeVariantType>(array: &[T]) -> Self {
716        let type_ = T::static_variant_type();
717
718        unsafe {
719            from_glib_none(ffi::g_variant_new_fixed_array(
720                type_.as_ptr(),
721                array.as_ptr() as ffi::gconstpointer,
722                array.len(),
723                mem::size_of::<T>(),
724            ))
725        }
726    }
727
728    // rustdoc-stripper-ignore-next
729    /// Creates a new Variant tuple from children.
730    #[doc(alias = "g_variant_new_tuple")]
731    pub fn tuple_from_iter(children: impl IntoIterator<Item = impl AsRef<Variant>>) -> Self {
732        unsafe {
733            let mut builder = mem::MaybeUninit::uninit();
734            ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
735            let mut builder = builder.assume_init();
736            for value in children.into_iter() {
737                ffi::g_variant_builder_add_value(&mut builder, value.as_ref().to_glib_none().0);
738            }
739            from_glib_none(ffi::g_variant_builder_end(&mut builder))
740        }
741    }
742
743    // rustdoc-stripper-ignore-next
744    /// Creates a new dictionary entry Variant.
745    ///
746    /// [DictEntry] should be preferred over this when the types are known statically.
747    #[doc(alias = "g_variant_new_dict_entry")]
748    pub fn from_dict_entry(key: &Variant, value: &Variant) -> Self {
749        unsafe {
750            from_glib_none(ffi::g_variant_new_dict_entry(
751                key.to_glib_none().0,
752                value.to_glib_none().0,
753            ))
754        }
755    }
756
757    // rustdoc-stripper-ignore-next
758    /// Creates a new maybe Variant.
759    #[doc(alias = "g_variant_new_maybe")]
760    pub fn from_maybe<T: StaticVariantType>(child: Option<&Variant>) -> Self {
761        let type_ = T::static_variant_type();
762        match child {
763            Some(child) => {
764                assert_eq!(type_, child.type_());
765
766                Self::from_some(child)
767            }
768            None => Self::from_none(&type_),
769        }
770    }
771
772    // rustdoc-stripper-ignore-next
773    /// Creates a new maybe Variant from a child.
774    #[doc(alias = "g_variant_new_maybe")]
775    pub fn from_some(child: &Variant) -> Self {
776        unsafe {
777            from_glib_none(ffi::g_variant_new_maybe(
778                ptr::null(),
779                child.to_glib_none().0,
780            ))
781        }
782    }
783
784    // rustdoc-stripper-ignore-next
785    /// Creates a new maybe Variant with Nothing.
786    #[doc(alias = "g_variant_new_maybe")]
787    pub fn from_none(type_: &VariantTy) -> Self {
788        unsafe {
789            from_glib_none(ffi::g_variant_new_maybe(
790                type_.to_glib_none().0,
791                ptr::null_mut(),
792            ))
793        }
794    }
795
796    // rustdoc-stripper-ignore-next
797    /// Extract the value of a maybe Variant.
798    ///
799    /// Returns the child value, or `None` if the value is Nothing.
800    ///
801    /// # Panics
802    ///
803    /// Panics if the variant is not maybe-typed.
804    #[inline]
805    pub fn as_maybe(&self) -> Option<Variant> {
806        assert!(self.type_().is_maybe());
807
808        unsafe { from_glib_full(ffi::g_variant_get_maybe(self.to_glib_none().0)) }
809    }
810
811    // rustdoc-stripper-ignore-next
812    /// Pretty-print the contents of this variant in a human-readable form.
813    ///
814    /// A variant can be recreated from this output via [`Variant::parse`].
815    // rustdoc-stripper-ignore-next-stop
816    /// Pretty-prints @self in the format understood by g_variant_parse().
817    ///
818    /// The format is described [here](gvariant-text-format.html).
819    ///
820    /// If @type_annotate is [`true`], then type information is included in
821    /// the output.
822    /// ## `type_annotate`
823    /// [`true`] if type information should be included in
824    ///                 the output
825    ///
826    /// # Returns
827    ///
828    /// a newly-allocated string holding the result.
829    // rustdoc-stripper-ignore-next-stop
830    /// Pretty-prints @self in the format understood by g_variant_parse().
831    ///
832    /// The format is described [here](gvariant-text-format.html).
833    ///
834    /// If @type_annotate is [`true`], then type information is included in
835    /// the output.
836    /// ## `type_annotate`
837    /// [`true`] if type information should be included in
838    ///                 the output
839    ///
840    /// # Returns
841    ///
842    /// a newly-allocated string holding the result.
843    #[doc(alias = "g_variant_print")]
844    pub fn print(&self, type_annotate: bool) -> crate::GString {
845        unsafe {
846            from_glib_full(ffi::g_variant_print(
847                self.to_glib_none().0,
848                type_annotate.into_glib(),
849            ))
850        }
851    }
852
853    // rustdoc-stripper-ignore-next
854    /// Parses a GVariant from the text representation produced by [`print()`](Self::print).
855    #[doc(alias = "g_variant_parse")]
856    pub fn parse(type_: Option<&VariantTy>, text: &str) -> Result<Self, crate::Error> {
857        unsafe {
858            let mut error = ptr::null_mut();
859            let text = text.as_bytes().as_ptr_range();
860            let variant = ffi::g_variant_parse(
861                type_.to_glib_none().0,
862                text.start as *const _,
863                text.end as *const _,
864                ptr::null_mut(),
865                &mut error,
866            );
867            if variant.is_null() {
868                debug_assert!(!error.is_null());
869                Err(from_glib_full(error))
870            } else {
871                debug_assert!(error.is_null());
872                Ok(from_glib_full(variant))
873            }
874        }
875    }
876
877    // rustdoc-stripper-ignore-next
878    /// Constructs a new serialized-mode GVariant instance.
879    // rustdoc-stripper-ignore-next-stop
880    /// Constructs a new serialized-mode #GVariant instance.  This is the
881    /// inner interface for creation of new serialized values that gets
882    /// called from various functions in gvariant.c.
883    ///
884    /// A reference is taken on @bytes.
885    ///
886    /// The data in @bytes must be aligned appropriately for the @type_ being loaded.
887    /// Otherwise this function will internally create a copy of the memory (since
888    /// GLib 2.60) or (in older versions) fail and exit the process.
889    /// ## `type_`
890    /// a #GVariantType
891    /// ## `bytes`
892    /// a #GBytes
893    /// ## `trusted`
894    /// if the contents of @bytes are trusted
895    ///
896    /// # Returns
897    ///
898    /// a new #GVariant with a floating reference
899    // rustdoc-stripper-ignore-next-stop
900    /// Constructs a new serialized-mode #GVariant instance.  This is the
901    /// inner interface for creation of new serialized values that gets
902    /// called from various functions in gvariant.c.
903    ///
904    /// A reference is taken on @bytes.
905    ///
906    /// The data in @bytes must be aligned appropriately for the @type_ being loaded.
907    /// Otherwise this function will internally create a copy of the memory (since
908    /// GLib 2.60) or (in older versions) fail and exit the process.
909    /// ## `type_`
910    /// a #GVariantType
911    /// ## `bytes`
912    /// a #GBytes
913    /// ## `trusted`
914    /// if the contents of @bytes are trusted
915    ///
916    /// # Returns
917    ///
918    /// a new #GVariant with a floating reference
919    #[doc(alias = "g_variant_new_from_bytes")]
920    pub fn from_bytes<T: StaticVariantType>(bytes: &Bytes) -> Self {
921        Variant::from_bytes_with_type(bytes, &T::static_variant_type())
922    }
923
924    // rustdoc-stripper-ignore-next
925    /// Constructs a new serialized-mode GVariant instance.
926    ///
927    /// This is the same as `from_bytes`, except that checks on the passed
928    /// data are skipped.
929    ///
930    /// You should not use this function on data from external sources.
931    ///
932    /// # Safety
933    ///
934    /// Since the data is not validated, this is potentially dangerous if called
935    /// on bytes which are not guaranteed to have come from serialising another
936    /// Variant.  The caller is responsible for ensuring bad data is not passed in.
937    pub unsafe fn from_bytes_trusted<T: StaticVariantType>(bytes: &Bytes) -> Self {
938        unsafe { Variant::from_bytes_with_type_trusted(bytes, &T::static_variant_type()) }
939    }
940
941    // rustdoc-stripper-ignore-next
942    /// Constructs a new serialized-mode GVariant instance.
943    // rustdoc-stripper-ignore-next-stop
944    /// Creates a new #GVariant instance from serialized data.
945    ///
946    /// @type_ is the type of #GVariant instance that will be constructed.
947    /// The interpretation of @data depends on knowing the type.
948    ///
949    /// @data is not modified by this function and must remain valid with an
950    /// unchanging value until such a time as @notify is called with
951    /// @user_data.  If the contents of @data change before that time then
952    /// the result is undefined.
953    ///
954    /// If @data is trusted to be serialized data in normal form then
955    /// @trusted should be [`true`].  This applies to serialized data created
956    /// within this process or read from a trusted location on the disk (such
957    /// as a file installed in /usr/lib alongside your application).  You
958    /// should set trusted to [`false`] if @data is read from the network, a
959    /// file in the user's home directory, etc.
960    ///
961    /// If @data was not stored in this machine's native endianness, any multi-byte
962    /// numeric values in the returned variant will also be in non-native
963    /// endianness. g_variant_byteswap() can be used to recover the original values.
964    ///
965    /// @notify will be called with @user_data when @data is no longer
966    /// needed.  The exact time of this call is unspecified and might even be
967    /// before this function returns.
968    ///
969    /// Note: @data must be backed by memory that is aligned appropriately for the
970    /// @type_ being loaded. Otherwise this function will internally create a copy of
971    /// the memory (since GLib 2.60) or (in older versions) fail and exit the
972    /// process.
973    /// ## `type_`
974    /// a definite #GVariantType
975    /// ## `data`
976    /// the serialized data
977    /// ## `trusted`
978    /// [`true`] if @data is definitely in normal form
979    /// ## `notify`
980    /// function to call when @data is no longer needed
981    ///
982    /// # Returns
983    ///
984    /// a new floating #GVariant of type @type_
985    // rustdoc-stripper-ignore-next-stop
986    /// Creates a new #GVariant instance from serialized data.
987    ///
988    /// @type_ is the type of #GVariant instance that will be constructed.
989    /// The interpretation of @data depends on knowing the type.
990    ///
991    /// @data is not modified by this function and must remain valid with an
992    /// unchanging value until such a time as @notify is called with
993    /// @user_data.  If the contents of @data change before that time then
994    /// the result is undefined.
995    ///
996    /// If @data is trusted to be serialized data in normal form then
997    /// @trusted should be [`true`].  This applies to serialized data created
998    /// within this process or read from a trusted location on the disk (such
999    /// as a file installed in /usr/lib alongside your application).  You
1000    /// should set trusted to [`false`] if @data is read from the network, a
1001    /// file in the user's home directory, etc.
1002    ///
1003    /// If @data was not stored in this machine's native endianness, any multi-byte
1004    /// numeric values in the returned variant will also be in non-native
1005    /// endianness. g_variant_byteswap() can be used to recover the original values.
1006    ///
1007    /// @notify will be called with @user_data when @data is no longer
1008    /// needed.  The exact time of this call is unspecified and might even be
1009    /// before this function returns.
1010    ///
1011    /// Note: @data must be backed by memory that is aligned appropriately for the
1012    /// @type_ being loaded. Otherwise this function will internally create a copy of
1013    /// the memory (since GLib 2.60) or (in older versions) fail and exit the
1014    /// process.
1015    /// ## `type_`
1016    /// a definite #GVariantType
1017    /// ## `data`
1018    /// the serialized data
1019    /// ## `trusted`
1020    /// [`true`] if @data is definitely in normal form
1021    /// ## `notify`
1022    /// function to call when @data is no longer needed
1023    ///
1024    /// # Returns
1025    ///
1026    /// a new floating #GVariant of type @type_
1027    #[doc(alias = "g_variant_new_from_data")]
1028    pub fn from_data<T: StaticVariantType, A: AsRef<[u8]> + 'static>(data: A) -> Self {
1029        Variant::from_data_with_type(data, &T::static_variant_type())
1030    }
1031
1032    // rustdoc-stripper-ignore-next
1033    /// Constructs a new serialized-mode GVariant instance.
1034    ///
1035    /// This is the same as `from_data`, except that checks on the passed
1036    /// data are skipped.
1037    ///
1038    /// You should not use this function on data from external sources.
1039    ///
1040    /// # Safety
1041    ///
1042    /// Since the data is not validated, this is potentially dangerous if called
1043    /// on bytes which are not guaranteed to have come from serialising another
1044    /// Variant.  The caller is responsible for ensuring bad data is not passed in.
1045    pub unsafe fn from_data_trusted<T: StaticVariantType, A: AsRef<[u8]> + 'static>(
1046        data: A,
1047    ) -> Self {
1048        unsafe { Variant::from_data_with_type_trusted(data, &T::static_variant_type()) }
1049    }
1050
1051    // rustdoc-stripper-ignore-next
1052    /// Constructs a new serialized-mode GVariant instance with a given type.
1053    #[doc(alias = "g_variant_new_from_bytes")]
1054    pub fn from_bytes_with_type(bytes: &Bytes, type_: &VariantTy) -> Self {
1055        unsafe {
1056            from_glib_none(ffi::g_variant_new_from_bytes(
1057                type_.as_ptr() as *const _,
1058                bytes.to_glib_none().0,
1059                false.into_glib(),
1060            ))
1061        }
1062    }
1063
1064    // rustdoc-stripper-ignore-next
1065    /// Constructs a new serialized-mode GVariant instance with a given type.
1066    ///
1067    /// This is the same as `from_bytes`, except that checks on the passed
1068    /// data are skipped.
1069    ///
1070    /// You should not use this function on data from external sources.
1071    ///
1072    /// # Safety
1073    ///
1074    /// Since the data is not validated, this is potentially dangerous if called
1075    /// on bytes which are not guaranteed to have come from serialising another
1076    /// Variant.  The caller is responsible for ensuring bad data is not passed in.
1077    pub unsafe fn from_bytes_with_type_trusted(bytes: &Bytes, type_: &VariantTy) -> Self {
1078        unsafe {
1079            from_glib_none(ffi::g_variant_new_from_bytes(
1080                type_.as_ptr() as *const _,
1081                bytes.to_glib_none().0,
1082                true.into_glib(),
1083            ))
1084        }
1085    }
1086
1087    // rustdoc-stripper-ignore-next
1088    /// Constructs a new serialized-mode GVariant instance with a given type.
1089    #[doc(alias = "g_variant_new_from_data")]
1090    pub fn from_data_with_type<A: AsRef<[u8]> + 'static>(data: A, type_: &VariantTy) -> Self {
1091        unsafe {
1092            let data = Box::new(data);
1093            let (data_ptr, len) = {
1094                let data = (*data).as_ref();
1095                (data.as_ptr(), data.len())
1096            };
1097
1098            unsafe extern "C" fn free_data<A: AsRef<[u8]>>(ptr: ffi::gpointer) {
1099                unsafe {
1100                    let _ = Box::from_raw(ptr as *mut A);
1101                }
1102            }
1103
1104            from_glib_none(ffi::g_variant_new_from_data(
1105                type_.as_ptr() as *const _,
1106                data_ptr as ffi::gconstpointer,
1107                len,
1108                false.into_glib(),
1109                Some(free_data::<A>),
1110                Box::into_raw(data) as ffi::gpointer,
1111            ))
1112        }
1113    }
1114
1115    // rustdoc-stripper-ignore-next
1116    /// Constructs a new serialized-mode GVariant instance with a given type.
1117    ///
1118    /// This is the same as `from_data`, except that checks on the passed
1119    /// data are skipped.
1120    ///
1121    /// You should not use this function on data from external sources.
1122    ///
1123    /// # Safety
1124    ///
1125    /// Since the data is not validated, this is potentially dangerous if called
1126    /// on bytes which are not guaranteed to have come from serialising another
1127    /// Variant.  The caller is responsible for ensuring bad data is not passed in.
1128    pub unsafe fn from_data_with_type_trusted<A: AsRef<[u8]> + 'static>(
1129        data: A,
1130        type_: &VariantTy,
1131    ) -> Self {
1132        unsafe {
1133            let data = Box::new(data);
1134            let (data_ptr, len) = {
1135                let data = (*data).as_ref();
1136                (data.as_ptr(), data.len())
1137            };
1138
1139            unsafe extern "C" fn free_data<A: AsRef<[u8]>>(ptr: ffi::gpointer) {
1140                unsafe {
1141                    let _ = Box::from_raw(ptr as *mut A);
1142                }
1143            }
1144
1145            from_glib_none(ffi::g_variant_new_from_data(
1146                type_.as_ptr() as *const _,
1147                data_ptr as ffi::gconstpointer,
1148                len,
1149                true.into_glib(),
1150                Some(free_data::<A>),
1151                Box::into_raw(data) as ffi::gpointer,
1152            ))
1153        }
1154    }
1155
1156    // rustdoc-stripper-ignore-next
1157    /// Returns the serialized form of a GVariant instance.
1158    // rustdoc-stripper-ignore-next-stop
1159    /// Returns a pointer to the serialized form of a #GVariant instance.
1160    /// The semantics of this function are exactly the same as
1161    /// g_variant_get_data(), except that the returned #GBytes holds
1162    /// a reference to the variant data.
1163    ///
1164    /// # Returns
1165    ///
1166    /// A new #GBytes representing the variant data
1167    // rustdoc-stripper-ignore-next-stop
1168    /// Returns a pointer to the serialized form of a #GVariant instance.
1169    /// The semantics of this function are exactly the same as
1170    /// g_variant_get_data(), except that the returned #GBytes holds
1171    /// a reference to the variant data.
1172    ///
1173    /// # Returns
1174    ///
1175    /// A new #GBytes representing the variant data
1176    #[doc(alias = "get_data_as_bytes")]
1177    #[doc(alias = "g_variant_get_data_as_bytes")]
1178    pub fn data_as_bytes(&self) -> Bytes {
1179        unsafe { from_glib_full(ffi::g_variant_get_data_as_bytes(self.to_glib_none().0)) }
1180    }
1181
1182    // rustdoc-stripper-ignore-next
1183    /// Returns the serialized form of a GVariant instance.
1184    // rustdoc-stripper-ignore-next-stop
1185    /// Returns a pointer to the serialized form of a #GVariant instance.
1186    /// The returned data may not be in fully-normalised form if read from an
1187    /// untrusted source.  The returned data must not be freed; it remains
1188    /// valid for as long as @self exists.
1189    ///
1190    /// If @self is a fixed-sized value that was deserialized from a
1191    /// corrupted serialized container then [`None`] may be returned.  In this
1192    /// case, the proper thing to do is typically to use the appropriate
1193    /// number of nul bytes in place of @self.  If @self is not fixed-sized
1194    /// then [`None`] is never returned.
1195    ///
1196    /// In the case that @self is already in serialized form, this function
1197    /// is O(1).  If the value is not already in serialized form,
1198    /// serialization occurs implicitly and is approximately O(n) in the size
1199    /// of the result.
1200    ///
1201    /// To deserialize the data returned by this function, in addition to the
1202    /// serialized data, you must know the type of the #GVariant, and (if the
1203    /// machine might be different) the endianness of the machine that stored
1204    /// it. As a result, file formats or network messages that incorporate
1205    /// serialized #GVariants must include this information either
1206    /// implicitly (for instance "the file always contains a
1207    /// `G_VARIANT_TYPE_VARIANT` and it is always in little-endian order") or
1208    /// explicitly (by storing the type and/or endianness in addition to the
1209    /// serialized data).
1210    ///
1211    /// # Returns
1212    ///
1213    /// the serialized form of @self, or [`None`]
1214    // rustdoc-stripper-ignore-next-stop
1215    /// Returns a pointer to the serialized form of a #GVariant instance.
1216    /// The returned data may not be in fully-normalised form if read from an
1217    /// untrusted source.  The returned data must not be freed; it remains
1218    /// valid for as long as @self exists.
1219    ///
1220    /// If @self is a fixed-sized value that was deserialized from a
1221    /// corrupted serialized container then [`None`] may be returned.  In this
1222    /// case, the proper thing to do is typically to use the appropriate
1223    /// number of nul bytes in place of @self.  If @self is not fixed-sized
1224    /// then [`None`] is never returned.
1225    ///
1226    /// In the case that @self is already in serialized form, this function
1227    /// is O(1).  If the value is not already in serialized form,
1228    /// serialization occurs implicitly and is approximately O(n) in the size
1229    /// of the result.
1230    ///
1231    /// To deserialize the data returned by this function, in addition to the
1232    /// serialized data, you must know the type of the #GVariant, and (if the
1233    /// machine might be different) the endianness of the machine that stored
1234    /// it. As a result, file formats or network messages that incorporate
1235    /// serialized #GVariants must include this information either
1236    /// implicitly (for instance "the file always contains a
1237    /// `G_VARIANT_TYPE_VARIANT` and it is always in little-endian order") or
1238    /// explicitly (by storing the type and/or endianness in addition to the
1239    /// serialized data).
1240    ///
1241    /// # Returns
1242    ///
1243    /// the serialized form of @self, or [`None`]
1244    #[doc(alias = "g_variant_get_data")]
1245    pub fn data(&self) -> &[u8] {
1246        unsafe {
1247            let selfv = self.to_glib_none();
1248            let len = ffi::g_variant_get_size(selfv.0);
1249            if len == 0 {
1250                return &[];
1251            }
1252            let ptr = ffi::g_variant_get_data(selfv.0);
1253            slice::from_raw_parts(ptr as *const _, len as _)
1254        }
1255    }
1256
1257    // rustdoc-stripper-ignore-next
1258    /// Returns the size of serialized form of a GVariant instance.
1259    // rustdoc-stripper-ignore-next-stop
1260    /// Determines the number of bytes that would be required to store @self
1261    /// with g_variant_store().
1262    ///
1263    /// If @self has a fixed-sized type then this function always returned
1264    /// that fixed size.
1265    ///
1266    /// In the case that @self is already in serialized form or the size has
1267    /// already been calculated (ie: this function has been called before)
1268    /// then this function is O(1).  Otherwise, the size is calculated, an
1269    /// operation which is approximately O(n) in the number of values
1270    /// involved.
1271    ///
1272    /// # Returns
1273    ///
1274    /// the serialized size of @self
1275    // rustdoc-stripper-ignore-next-stop
1276    /// Determines the number of bytes that would be required to store @self
1277    /// with g_variant_store().
1278    ///
1279    /// If @self has a fixed-sized type then this function always returned
1280    /// that fixed size.
1281    ///
1282    /// In the case that @self is already in serialized form or the size has
1283    /// already been calculated (ie: this function has been called before)
1284    /// then this function is O(1).  Otherwise, the size is calculated, an
1285    /// operation which is approximately O(n) in the number of values
1286    /// involved.
1287    ///
1288    /// # Returns
1289    ///
1290    /// the serialized size of @self
1291    #[doc(alias = "g_variant_get_size")]
1292    pub fn size(&self) -> usize {
1293        unsafe { ffi::g_variant_get_size(self.to_glib_none().0) }
1294    }
1295
1296    // rustdoc-stripper-ignore-next
1297    /// Stores the serialized form of a GVariant instance into the given slice.
1298    ///
1299    /// The slice needs to be big enough.
1300    // rustdoc-stripper-ignore-next-stop
1301    /// Stores the serialized form of @self at @data.  @data should be
1302    /// large enough.  See g_variant_get_size().
1303    ///
1304    /// The stored data is in machine native byte order but may not be in
1305    /// fully-normalised form if read from an untrusted source.  See
1306    /// g_variant_get_normal_form() for a solution.
1307    ///
1308    /// As with g_variant_get_data(), to be able to deserialize the
1309    /// serialized variant successfully, its type and (if the destination
1310    /// machine might be different) its endianness must also be available.
1311    ///
1312    /// This function is approximately O(n) in the size of @data.
1313    // rustdoc-stripper-ignore-next-stop
1314    /// Stores the serialized form of @self at @data.  @data should be
1315    /// large enough.  See g_variant_get_size().
1316    ///
1317    /// The stored data is in machine native byte order but may not be in
1318    /// fully-normalised form if read from an untrusted source.  See
1319    /// g_variant_get_normal_form() for a solution.
1320    ///
1321    /// As with g_variant_get_data(), to be able to deserialize the
1322    /// serialized variant successfully, its type and (if the destination
1323    /// machine might be different) its endianness must also be available.
1324    ///
1325    /// This function is approximately O(n) in the size of @data.
1326    #[doc(alias = "g_variant_store")]
1327    pub fn store(&self, data: &mut [u8]) -> Result<usize, crate::BoolError> {
1328        unsafe {
1329            let size = ffi::g_variant_get_size(self.to_glib_none().0);
1330            if data.len() < size {
1331                return Err(bool_error!("Provided slice is too small"));
1332            }
1333
1334            ffi::g_variant_store(self.to_glib_none().0, data.as_mut_ptr() as ffi::gpointer);
1335
1336            Ok(size)
1337        }
1338    }
1339
1340    // rustdoc-stripper-ignore-next
1341    /// Returns a copy of the variant in normal form.
1342    // rustdoc-stripper-ignore-next-stop
1343    /// Gets a #GVariant instance that has the same value as @self and is
1344    /// trusted to be in normal form.
1345    ///
1346    /// If @self is already trusted to be in normal form then a new
1347    /// reference to @self is returned.
1348    ///
1349    /// If @self is not already trusted, then it is scanned to check if it
1350    /// is in normal form.  If it is found to be in normal form then it is
1351    /// marked as trusted and a new reference to it is returned.
1352    ///
1353    /// If @self is found not to be in normal form then a new trusted
1354    /// #GVariant is created with the same value as @self. The non-normal parts of
1355    /// @self will be replaced with default values which are guaranteed to be in
1356    /// normal form.
1357    ///
1358    /// It makes sense to call this function if you've received #GVariant
1359    /// data from untrusted sources and you want to ensure your serialized
1360    /// output is definitely in normal form.
1361    ///
1362    /// If @self is already in normal form, a new reference will be returned
1363    /// (which will be floating if @self is floating). If it is not in normal form,
1364    /// the newly created #GVariant will be returned with a single non-floating
1365    /// reference. Typically, g_variant_take_ref() should be called on the return
1366    /// value from this function to guarantee ownership of a single non-floating
1367    /// reference to it.
1368    ///
1369    /// # Returns
1370    ///
1371    /// a trusted #GVariant
1372    // rustdoc-stripper-ignore-next-stop
1373    /// Gets a #GVariant instance that has the same value as @self and is
1374    /// trusted to be in normal form.
1375    ///
1376    /// If @self is already trusted to be in normal form then a new
1377    /// reference to @self is returned.
1378    ///
1379    /// If @self is not already trusted, then it is scanned to check if it
1380    /// is in normal form.  If it is found to be in normal form then it is
1381    /// marked as trusted and a new reference to it is returned.
1382    ///
1383    /// If @self is found not to be in normal form then a new trusted
1384    /// #GVariant is created with the same value as @self. The non-normal parts of
1385    /// @self will be replaced with default values which are guaranteed to be in
1386    /// normal form.
1387    ///
1388    /// It makes sense to call this function if you've received #GVariant
1389    /// data from untrusted sources and you want to ensure your serialized
1390    /// output is definitely in normal form.
1391    ///
1392    /// If @self is already in normal form, a new reference will be returned
1393    /// (which will be floating if @self is floating). If it is not in normal form,
1394    /// the newly created #GVariant will be returned with a single non-floating
1395    /// reference. Typically, g_variant_take_ref() should be called on the return
1396    /// value from this function to guarantee ownership of a single non-floating
1397    /// reference to it.
1398    ///
1399    /// # Returns
1400    ///
1401    /// a trusted #GVariant
1402    #[doc(alias = "g_variant_get_normal_form")]
1403    #[must_use]
1404    pub fn normal_form(&self) -> Self {
1405        unsafe { from_glib_full(ffi::g_variant_get_normal_form(self.to_glib_none().0)) }
1406    }
1407
1408    // rustdoc-stripper-ignore-next
1409    /// Returns a copy of the variant in the opposite endianness.
1410    // rustdoc-stripper-ignore-next-stop
1411    /// Performs a byteswapping operation on the contents of @self.  The
1412    /// result is that all multi-byte numeric data contained in @self is
1413    /// byteswapped.  That includes 16, 32, and 64bit signed and unsigned
1414    /// integers as well as file handles and double precision floating point
1415    /// values.
1416    ///
1417    /// This function is an identity mapping on any value that does not
1418    /// contain multi-byte numeric data.  That include strings, booleans,
1419    /// bytes and containers containing only these things (recursively).
1420    ///
1421    /// While this function can safely handle untrusted, non-normal data, it is
1422    /// recommended to check whether the input is in normal form beforehand, using
1423    /// g_variant_is_normal_form(), and to reject non-normal inputs if your
1424    /// application can be strict about what inputs it rejects.
1425    ///
1426    /// The returned value is always in normal form and is marked as trusted.
1427    /// A full, not floating, reference is returned.
1428    ///
1429    /// # Returns
1430    ///
1431    /// the byteswapped form of @self
1432    // rustdoc-stripper-ignore-next-stop
1433    /// Performs a byteswapping operation on the contents of @self.  The
1434    /// result is that all multi-byte numeric data contained in @self is
1435    /// byteswapped.  That includes 16, 32, and 64bit signed and unsigned
1436    /// integers as well as file handles and double precision floating point
1437    /// values.
1438    ///
1439    /// This function is an identity mapping on any value that does not
1440    /// contain multi-byte numeric data.  That include strings, booleans,
1441    /// bytes and containers containing only these things (recursively).
1442    ///
1443    /// While this function can safely handle untrusted, non-normal data, it is
1444    /// recommended to check whether the input is in normal form beforehand, using
1445    /// g_variant_is_normal_form(), and to reject non-normal inputs if your
1446    /// application can be strict about what inputs it rejects.
1447    ///
1448    /// The returned value is always in normal form and is marked as trusted.
1449    /// A full, not floating, reference is returned.
1450    ///
1451    /// # Returns
1452    ///
1453    /// the byteswapped form of @self
1454    #[doc(alias = "g_variant_byteswap")]
1455    #[must_use]
1456    pub fn byteswap(&self) -> Self {
1457        unsafe { from_glib_full(ffi::g_variant_byteswap(self.to_glib_none().0)) }
1458    }
1459
1460    // rustdoc-stripper-ignore-next
1461    /// Determines the number of children in a container GVariant instance.
1462    // rustdoc-stripper-ignore-next-stop
1463    /// Determines the number of children in a container #GVariant instance.
1464    /// This includes variants, maybes, arrays, tuples and dictionary
1465    /// entries.  It is an error to call this function on any other type of
1466    /// #GVariant.
1467    ///
1468    /// For variants, the return value is always 1.  For values with maybe
1469    /// types, it is always zero or one.  For arrays, it is the length of the
1470    /// array.  For tuples it is the number of tuple items (which depends
1471    /// only on the type).  For dictionary entries, it is always 2
1472    ///
1473    /// This function is O(1).
1474    ///
1475    /// # Returns
1476    ///
1477    /// the number of children in the container
1478    // rustdoc-stripper-ignore-next-stop
1479    /// Determines the number of children in a container #GVariant instance.
1480    /// This includes variants, maybes, arrays, tuples and dictionary
1481    /// entries.  It is an error to call this function on any other type of
1482    /// #GVariant.
1483    ///
1484    /// For variants, the return value is always 1.  For values with maybe
1485    /// types, it is always zero or one.  For arrays, it is the length of the
1486    /// array.  For tuples it is the number of tuple items (which depends
1487    /// only on the type).  For dictionary entries, it is always 2
1488    ///
1489    /// This function is O(1).
1490    ///
1491    /// # Returns
1492    ///
1493    /// the number of children in the container
1494    #[doc(alias = "g_variant_n_children")]
1495    pub fn n_children(&self) -> usize {
1496        assert!(self.is_container());
1497
1498        unsafe { ffi::g_variant_n_children(self.to_glib_none().0) }
1499    }
1500
1501    // rustdoc-stripper-ignore-next
1502    /// Create an iterator over items in the variant.
1503    ///
1504    /// Note that this heap allocates a variant for each element,
1505    /// which can be particularly expensive for large arrays.
1506    pub fn iter(&self) -> VariantIter {
1507        assert!(self.is_container());
1508
1509        VariantIter::new(self.clone())
1510    }
1511
1512    // rustdoc-stripper-ignore-next
1513    /// Create an iterator over borrowed strings from a GVariant of type `as` (array of string).
1514    ///
1515    /// This will fail if the variant is not an array of with
1516    /// the expected child type.
1517    ///
1518    /// A benefit of this API over [`Self::iter()`] is that it
1519    /// minimizes allocation, and provides strongly typed access.
1520    ///
1521    /// ```
1522    /// # use glib::prelude::*;
1523    /// let strs = &["foo", "bar"];
1524    /// let strs_variant: glib::Variant = strs.to_variant();
1525    /// for s in strs_variant.array_iter_str()? {
1526    ///     println!("{}", s);
1527    /// }
1528    /// # Ok::<(), Box<dyn std::error::Error>>(())
1529    /// ```
1530    pub fn array_iter_str(&self) -> Result<VariantStrIter<'_>, VariantTypeMismatchError> {
1531        let child_ty = String::static_variant_type();
1532        let actual_ty = self.type_();
1533        let expected_ty = child_ty.as_array();
1534        if actual_ty != expected_ty {
1535            return Err(VariantTypeMismatchError {
1536                actual: actual_ty.to_owned(),
1537                expected: expected_ty.into_owned(),
1538            });
1539        }
1540
1541        Ok(VariantStrIter::new(self))
1542    }
1543
1544    // rustdoc-stripper-ignore-next
1545    /// Return whether this Variant is a container type.
1546    // rustdoc-stripper-ignore-next-stop
1547    /// Checks if @self is a container.
1548    ///
1549    /// # Returns
1550    ///
1551    /// [`true`] if @self is a container
1552    // rustdoc-stripper-ignore-next-stop
1553    /// Checks if @self is a container.
1554    ///
1555    /// # Returns
1556    ///
1557    /// [`true`] if @self is a container
1558    #[doc(alias = "g_variant_is_container")]
1559    pub fn is_container(&self) -> bool {
1560        unsafe { from_glib(ffi::g_variant_is_container(self.to_glib_none().0)) }
1561    }
1562
1563    // rustdoc-stripper-ignore-next
1564    /// Return whether this Variant is in normal form.
1565    // rustdoc-stripper-ignore-next-stop
1566    /// Checks if @self is in normal form.
1567    ///
1568    /// The main reason to do this is to detect if a given chunk of
1569    /// serialized data is in normal form: load the data into a #GVariant
1570    /// using g_variant_new_from_data() and then use this function to
1571    /// check.
1572    ///
1573    /// If @self is found to be in normal form then it will be marked as
1574    /// being trusted.  If the value was already marked as being trusted then
1575    /// this function will immediately return [`true`].
1576    ///
1577    /// There may be implementation specific restrictions on deeply nested values.
1578    /// GVariant is guaranteed to handle nesting up to at least 64 levels.
1579    ///
1580    /// # Returns
1581    ///
1582    /// [`true`] if @self is in normal form
1583    // rustdoc-stripper-ignore-next-stop
1584    /// Checks if @self is in normal form.
1585    ///
1586    /// The main reason to do this is to detect if a given chunk of
1587    /// serialized data is in normal form: load the data into a #GVariant
1588    /// using g_variant_new_from_data() and then use this function to
1589    /// check.
1590    ///
1591    /// If @self is found to be in normal form then it will be marked as
1592    /// being trusted.  If the value was already marked as being trusted then
1593    /// this function will immediately return [`true`].
1594    ///
1595    /// There may be implementation specific restrictions on deeply nested values.
1596    /// GVariant is guaranteed to handle nesting up to at least 64 levels.
1597    ///
1598    /// # Returns
1599    ///
1600    /// [`true`] if @self is in normal form
1601    #[doc(alias = "g_variant_is_normal_form")]
1602    pub fn is_normal_form(&self) -> bool {
1603        unsafe { from_glib(ffi::g_variant_is_normal_form(self.to_glib_none().0)) }
1604    }
1605
1606    // rustdoc-stripper-ignore-next
1607    /// Return whether input string is a valid `VariantClass::ObjectPath`.
1608    // rustdoc-stripper-ignore-next-stop
1609    /// Determines if a given string is a valid D-Bus object path.  You
1610    /// should ensure that a string is a valid D-Bus object path before
1611    /// passing it to g_variant_new_object_path().
1612    ///
1613    /// A valid object path starts with `/` followed by zero or more
1614    /// sequences of characters separated by `/` characters.  Each sequence
1615    /// must contain only the characters `[A-Z][a-z][0-9]_`.  No sequence
1616    /// (including the one following the final `/` character) may be empty.
1617    /// ## `string`
1618    /// a normal C nul-terminated string
1619    ///
1620    /// # Returns
1621    ///
1622    /// [`true`] if @string is a D-Bus object path
1623    // rustdoc-stripper-ignore-next-stop
1624    /// Determines if a given string is a valid D-Bus object path.  You
1625    /// should ensure that a string is a valid D-Bus object path before
1626    /// passing it to g_variant_new_object_path().
1627    ///
1628    /// A valid object path starts with `/` followed by zero or more
1629    /// sequences of characters separated by `/` characters.  Each sequence
1630    /// must contain only the characters `[A-Z][a-z][0-9]_`.  No sequence
1631    /// (including the one following the final `/` character) may be empty.
1632    /// ## `string`
1633    /// a normal C nul-terminated string
1634    ///
1635    /// # Returns
1636    ///
1637    /// [`true`] if @string is a D-Bus object path
1638    #[doc(alias = "g_variant_is_object_path")]
1639    pub fn is_object_path(string: &str) -> bool {
1640        unsafe { from_glib(ffi::g_variant_is_object_path(string.to_glib_none().0)) }
1641    }
1642
1643    // rustdoc-stripper-ignore-next
1644    /// Return whether input string is a valid `VariantClass::Signature`.
1645    // rustdoc-stripper-ignore-next-stop
1646    /// Determines if a given string is a valid D-Bus type signature.  You
1647    /// should ensure that a string is a valid D-Bus type signature before
1648    /// passing it to g_variant_new_signature().
1649    ///
1650    /// D-Bus type signatures consist of zero or more definite #GVariantType
1651    /// strings in sequence.
1652    /// ## `string`
1653    /// a normal C nul-terminated string
1654    ///
1655    /// # Returns
1656    ///
1657    /// [`true`] if @string is a D-Bus type signature
1658    // rustdoc-stripper-ignore-next-stop
1659    /// Determines if a given string is a valid D-Bus type signature.  You
1660    /// should ensure that a string is a valid D-Bus type signature before
1661    /// passing it to g_variant_new_signature().
1662    ///
1663    /// D-Bus type signatures consist of zero or more definite #GVariantType
1664    /// strings in sequence.
1665    /// ## `string`
1666    /// a normal C nul-terminated string
1667    ///
1668    /// # Returns
1669    ///
1670    /// [`true`] if @string is a D-Bus type signature
1671    #[doc(alias = "g_variant_is_signature")]
1672    pub fn is_signature(string: &str) -> bool {
1673        unsafe { from_glib(ffi::g_variant_is_signature(string.to_glib_none().0)) }
1674    }
1675}
1676
1677unsafe impl Send for Variant {}
1678unsafe impl Sync for Variant {}
1679
1680impl fmt::Debug for Variant {
1681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1682        f.debug_struct("Variant")
1683            .field("ptr", &ToGlibPtr::<*const _>::to_glib_none(self).0)
1684            .field("type", &self.type_())
1685            .field("value", &self.to_string())
1686            .finish()
1687    }
1688}
1689
1690impl fmt::Display for Variant {
1691    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1692        f.write_str(&self.print(true))
1693    }
1694}
1695
1696impl str::FromStr for Variant {
1697    type Err = crate::Error;
1698
1699    fn from_str(s: &str) -> Result<Self, Self::Err> {
1700        Self::parse(None, s)
1701    }
1702}
1703
1704impl PartialEq for Variant {
1705    #[doc(alias = "g_variant_equal")]
1706    fn eq(&self, other: &Self) -> bool {
1707        unsafe {
1708            from_glib(ffi::g_variant_equal(
1709                ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
1710                ToGlibPtr::<*const _>::to_glib_none(other).0 as *const _,
1711            ))
1712        }
1713    }
1714}
1715
1716impl Eq for Variant {}
1717
1718impl PartialOrd for Variant {
1719    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1720        unsafe {
1721            if ffi::g_variant_classify(self.to_glib_none().0)
1722                != ffi::g_variant_classify(other.to_glib_none().0)
1723            {
1724                return None;
1725            }
1726
1727            if self.is_container() {
1728                return None;
1729            }
1730
1731            let res = ffi::g_variant_compare(
1732                ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
1733                ToGlibPtr::<*const _>::to_glib_none(other).0 as *const _,
1734            );
1735
1736            Some(res.cmp(&0))
1737        }
1738    }
1739}
1740
1741impl Hash for Variant {
1742    #[doc(alias = "g_variant_hash")]
1743    fn hash<H: Hasher>(&self, state: &mut H) {
1744        unsafe {
1745            state.write_u32(ffi::g_variant_hash(
1746                ToGlibPtr::<*const _>::to_glib_none(self).0 as *const _,
1747            ))
1748        }
1749    }
1750}
1751
1752impl AsRef<Variant> for Variant {
1753    #[inline]
1754    fn as_ref(&self) -> &Self {
1755        self
1756    }
1757}
1758
1759// rustdoc-stripper-ignore-next
1760/// Converts to `Variant`.
1761pub trait ToVariant {
1762    // rustdoc-stripper-ignore-next
1763    /// Returns a `Variant` clone of `self`.
1764    fn to_variant(&self) -> Variant;
1765}
1766
1767// rustdoc-stripper-ignore-next
1768/// Extracts a value.
1769pub trait FromVariant: Sized + StaticVariantType {
1770    // rustdoc-stripper-ignore-next
1771    /// Tries to extract a value.
1772    ///
1773    /// Returns `Some` if the variant's type matches `Self`.
1774    fn from_variant(variant: &Variant) -> Option<Self>;
1775}
1776
1777// rustdoc-stripper-ignore-next
1778/// Returns `VariantType` of `Self`.
1779pub trait StaticVariantType {
1780    // rustdoc-stripper-ignore-next
1781    /// Returns the `VariantType` corresponding to `Self`.
1782    fn static_variant_type() -> Cow<'static, VariantTy>;
1783}
1784
1785impl StaticVariantType for Variant {
1786    fn static_variant_type() -> Cow<'static, VariantTy> {
1787        Cow::Borrowed(VariantTy::VARIANT)
1788    }
1789}
1790
1791impl<T: ?Sized + ToVariant> ToVariant for &T {
1792    fn to_variant(&self) -> Variant {
1793        <T as ToVariant>::to_variant(self)
1794    }
1795}
1796
1797impl<'a, T: Into<Variant> + Clone> From<&'a T> for Variant {
1798    #[inline]
1799    fn from(v: &'a T) -> Self {
1800        v.clone().into()
1801    }
1802}
1803
1804impl<T: ?Sized + StaticVariantType> StaticVariantType for &T {
1805    fn static_variant_type() -> Cow<'static, VariantTy> {
1806        <T as StaticVariantType>::static_variant_type()
1807    }
1808}
1809
1810macro_rules! impl_numeric {
1811    ($name:ty, $typ:expr, $new_fn:ident, $get_fn:ident) => {
1812        impl StaticVariantType for $name {
1813            fn static_variant_type() -> Cow<'static, VariantTy> {
1814                Cow::Borrowed($typ)
1815            }
1816        }
1817
1818        impl ToVariant for $name {
1819            fn to_variant(&self) -> Variant {
1820                unsafe { from_glib_none(ffi::$new_fn(*self)) }
1821            }
1822        }
1823
1824        impl From<$name> for Variant {
1825            #[inline]
1826            fn from(v: $name) -> Self {
1827                v.to_variant()
1828            }
1829        }
1830
1831        impl FromVariant for $name {
1832            fn from_variant(variant: &Variant) -> Option<Self> {
1833                unsafe {
1834                    if variant.is::<Self>() {
1835                        Some(ffi::$get_fn(variant.to_glib_none().0))
1836                    } else {
1837                        None
1838                    }
1839                }
1840            }
1841        }
1842    };
1843}
1844
1845impl_numeric!(u8, VariantTy::BYTE, g_variant_new_byte, g_variant_get_byte);
1846impl_numeric!(
1847    i16,
1848    VariantTy::INT16,
1849    g_variant_new_int16,
1850    g_variant_get_int16
1851);
1852impl_numeric!(
1853    u16,
1854    VariantTy::UINT16,
1855    g_variant_new_uint16,
1856    g_variant_get_uint16
1857);
1858impl_numeric!(
1859    i32,
1860    VariantTy::INT32,
1861    g_variant_new_int32,
1862    g_variant_get_int32
1863);
1864impl_numeric!(
1865    u32,
1866    VariantTy::UINT32,
1867    g_variant_new_uint32,
1868    g_variant_get_uint32
1869);
1870impl_numeric!(
1871    i64,
1872    VariantTy::INT64,
1873    g_variant_new_int64,
1874    g_variant_get_int64
1875);
1876impl_numeric!(
1877    u64,
1878    VariantTy::UINT64,
1879    g_variant_new_uint64,
1880    g_variant_get_uint64
1881);
1882impl_numeric!(
1883    f64,
1884    VariantTy::DOUBLE,
1885    g_variant_new_double,
1886    g_variant_get_double
1887);
1888
1889impl StaticVariantType for () {
1890    fn static_variant_type() -> Cow<'static, VariantTy> {
1891        Cow::Borrowed(VariantTy::UNIT)
1892    }
1893}
1894
1895impl ToVariant for () {
1896    fn to_variant(&self) -> Variant {
1897        unsafe { from_glib_none(ffi::g_variant_new_tuple(ptr::null(), 0)) }
1898    }
1899}
1900
1901impl From<()> for Variant {
1902    #[inline]
1903    fn from(_: ()) -> Self {
1904        ().to_variant()
1905    }
1906}
1907
1908impl FromVariant for () {
1909    fn from_variant(variant: &Variant) -> Option<Self> {
1910        if variant.is::<Self>() { Some(()) } else { None }
1911    }
1912}
1913
1914impl StaticVariantType for bool {
1915    fn static_variant_type() -> Cow<'static, VariantTy> {
1916        Cow::Borrowed(VariantTy::BOOLEAN)
1917    }
1918}
1919
1920impl ToVariant for bool {
1921    fn to_variant(&self) -> Variant {
1922        unsafe { from_glib_none(ffi::g_variant_new_boolean(self.into_glib())) }
1923    }
1924}
1925
1926impl From<bool> for Variant {
1927    #[inline]
1928    fn from(v: bool) -> Self {
1929        v.to_variant()
1930    }
1931}
1932
1933impl FromVariant for bool {
1934    fn from_variant(variant: &Variant) -> Option<Self> {
1935        unsafe {
1936            if variant.is::<Self>() {
1937                Some(from_glib(ffi::g_variant_get_boolean(
1938                    variant.to_glib_none().0,
1939                )))
1940            } else {
1941                None
1942            }
1943        }
1944    }
1945}
1946
1947impl StaticVariantType for String {
1948    fn static_variant_type() -> Cow<'static, VariantTy> {
1949        Cow::Borrowed(VariantTy::STRING)
1950    }
1951}
1952
1953impl ToVariant for String {
1954    fn to_variant(&self) -> Variant {
1955        self[..].to_variant()
1956    }
1957}
1958
1959impl From<String> for Variant {
1960    #[inline]
1961    fn from(s: String) -> Self {
1962        s.to_variant()
1963    }
1964}
1965
1966impl FromVariant for String {
1967    fn from_variant(variant: &Variant) -> Option<Self> {
1968        variant.str().map(String::from)
1969    }
1970}
1971
1972impl StaticVariantType for str {
1973    fn static_variant_type() -> Cow<'static, VariantTy> {
1974        String::static_variant_type()
1975    }
1976}
1977
1978impl ToVariant for str {
1979    fn to_variant(&self) -> Variant {
1980        unsafe { from_glib_none(ffi::g_variant_new_take_string(self.to_glib_full())) }
1981    }
1982}
1983
1984impl From<&str> for Variant {
1985    #[inline]
1986    fn from(s: &str) -> Self {
1987        s.to_variant()
1988    }
1989}
1990
1991impl StaticVariantType for std::path::PathBuf {
1992    fn static_variant_type() -> Cow<'static, VariantTy> {
1993        std::path::Path::static_variant_type()
1994    }
1995}
1996
1997impl ToVariant for std::path::PathBuf {
1998    fn to_variant(&self) -> Variant {
1999        self.as_path().to_variant()
2000    }
2001}
2002
2003impl From<std::path::PathBuf> for Variant {
2004    #[inline]
2005    fn from(p: std::path::PathBuf) -> Self {
2006        p.to_variant()
2007    }
2008}
2009
2010impl FromVariant for std::path::PathBuf {
2011    fn from_variant(variant: &Variant) -> Option<Self> {
2012        unsafe {
2013            let ptr = ffi::g_variant_get_bytestring(variant.to_glib_none().0);
2014            Some(crate::translate::c_to_path_buf(ptr as *const _))
2015        }
2016    }
2017}
2018
2019impl StaticVariantType for std::path::Path {
2020    fn static_variant_type() -> Cow<'static, VariantTy> {
2021        <&[u8]>::static_variant_type()
2022    }
2023}
2024
2025impl ToVariant for std::path::Path {
2026    fn to_variant(&self) -> Variant {
2027        let tmp = crate::translate::path_to_c(self);
2028        unsafe { from_glib_none(ffi::g_variant_new_bytestring(tmp.as_ptr() as *const u8)) }
2029    }
2030}
2031
2032impl From<&std::path::Path> for Variant {
2033    #[inline]
2034    fn from(p: &std::path::Path) -> Self {
2035        p.to_variant()
2036    }
2037}
2038
2039impl StaticVariantType for std::ffi::OsString {
2040    fn static_variant_type() -> Cow<'static, VariantTy> {
2041        std::ffi::OsStr::static_variant_type()
2042    }
2043}
2044
2045impl ToVariant for std::ffi::OsString {
2046    fn to_variant(&self) -> Variant {
2047        self.as_os_str().to_variant()
2048    }
2049}
2050
2051impl From<std::ffi::OsString> for Variant {
2052    #[inline]
2053    fn from(s: std::ffi::OsString) -> Self {
2054        s.to_variant()
2055    }
2056}
2057
2058impl FromVariant for std::ffi::OsString {
2059    fn from_variant(variant: &Variant) -> Option<Self> {
2060        unsafe {
2061            let ptr = ffi::g_variant_get_bytestring(variant.to_glib_none().0);
2062            Some(crate::translate::c_to_os_string(ptr as *const _))
2063        }
2064    }
2065}
2066
2067impl StaticVariantType for std::ffi::OsStr {
2068    fn static_variant_type() -> Cow<'static, VariantTy> {
2069        <&[u8]>::static_variant_type()
2070    }
2071}
2072
2073impl ToVariant for std::ffi::OsStr {
2074    fn to_variant(&self) -> Variant {
2075        let tmp = crate::translate::os_str_to_c(self);
2076        unsafe { from_glib_none(ffi::g_variant_new_bytestring(tmp.as_ptr() as *const u8)) }
2077    }
2078}
2079
2080impl From<&std::ffi::OsStr> for Variant {
2081    #[inline]
2082    fn from(s: &std::ffi::OsStr) -> Self {
2083        s.to_variant()
2084    }
2085}
2086
2087impl<T: StaticVariantType> StaticVariantType for Option<T> {
2088    fn static_variant_type() -> Cow<'static, VariantTy> {
2089        Cow::Owned(VariantType::new_maybe(&T::static_variant_type()))
2090    }
2091}
2092
2093impl<T: StaticVariantType + ToVariant> ToVariant for Option<T> {
2094    fn to_variant(&self) -> Variant {
2095        Variant::from_maybe::<T>(self.as_ref().map(|m| m.to_variant()).as_ref())
2096    }
2097}
2098
2099impl<T: StaticVariantType + Into<Variant>> From<Option<T>> for Variant {
2100    #[inline]
2101    fn from(v: Option<T>) -> Self {
2102        Variant::from_maybe::<T>(v.map(|v| v.into()).as_ref())
2103    }
2104}
2105
2106impl<T: StaticVariantType + FromVariant> FromVariant for Option<T> {
2107    fn from_variant(variant: &Variant) -> Option<Self> {
2108        unsafe {
2109            if variant.is::<Self>() {
2110                let c_child = ffi::g_variant_get_maybe(variant.to_glib_none().0);
2111                if !c_child.is_null() {
2112                    let child: Variant = from_glib_full(c_child);
2113
2114                    Some(T::from_variant(&child))
2115                } else {
2116                    Some(None)
2117                }
2118            } else {
2119                None
2120            }
2121        }
2122    }
2123}
2124
2125impl<T: StaticVariantType> StaticVariantType for [T] {
2126    fn static_variant_type() -> Cow<'static, VariantTy> {
2127        T::static_variant_type().as_array()
2128    }
2129}
2130
2131impl<T: StaticVariantType + ToVariant> ToVariant for [T] {
2132    fn to_variant(&self) -> Variant {
2133        unsafe {
2134            if self.is_empty() {
2135                return from_glib_none(ffi::g_variant_new_array(
2136                    T::static_variant_type().to_glib_none().0,
2137                    ptr::null(),
2138                    0,
2139                ));
2140            }
2141
2142            let mut builder = mem::MaybeUninit::uninit();
2143            ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2144            let mut builder = builder.assume_init();
2145            for value in self {
2146                let value = value.to_variant();
2147                ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
2148            }
2149            from_glib_none(ffi::g_variant_builder_end(&mut builder))
2150        }
2151    }
2152}
2153
2154impl<T: StaticVariantType + ToVariant> From<&[T]> for Variant {
2155    #[inline]
2156    fn from(s: &[T]) -> Self {
2157        s.to_variant()
2158    }
2159}
2160
2161impl<T: FromVariant> FromVariant for Vec<T> {
2162    fn from_variant(variant: &Variant) -> Option<Self> {
2163        if !variant.is_container() {
2164            return None;
2165        }
2166
2167        let mut vec = Vec::with_capacity(variant.n_children());
2168
2169        for i in 0..variant.n_children() {
2170            match variant.child_value(i).get() {
2171                Some(child) => vec.push(child),
2172                None => return None,
2173            }
2174        }
2175
2176        Some(vec)
2177    }
2178}
2179
2180impl<T: StaticVariantType + ToVariant> ToVariant for Vec<T> {
2181    fn to_variant(&self) -> Variant {
2182        self.as_slice().to_variant()
2183    }
2184}
2185
2186impl<T: StaticVariantType + Into<Variant>> From<Vec<T>> for Variant {
2187    fn from(v: Vec<T>) -> Self {
2188        unsafe {
2189            if v.is_empty() {
2190                return from_glib_none(ffi::g_variant_new_array(
2191                    T::static_variant_type().to_glib_none().0,
2192                    ptr::null(),
2193                    0,
2194                ));
2195            }
2196
2197            let mut builder = mem::MaybeUninit::uninit();
2198            ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2199            let mut builder = builder.assume_init();
2200            for value in v {
2201                let value = value.into();
2202                ffi::g_variant_builder_add_value(&mut builder, value.to_glib_none().0);
2203            }
2204            from_glib_none(ffi::g_variant_builder_end(&mut builder))
2205        }
2206    }
2207}
2208
2209impl<T: StaticVariantType> StaticVariantType for Vec<T> {
2210    fn static_variant_type() -> Cow<'static, VariantTy> {
2211        <[T]>::static_variant_type()
2212    }
2213}
2214
2215impl<K, V, H> FromVariant for HashMap<K, V, H>
2216where
2217    K: FromVariant + Eq + Hash,
2218    V: FromVariant,
2219    H: BuildHasher + Default,
2220{
2221    fn from_variant(variant: &Variant) -> Option<Self> {
2222        if !variant.is_container() {
2223            return None;
2224        }
2225
2226        let mut map = HashMap::default();
2227
2228        for i in 0..variant.n_children() {
2229            let entry = variant.child_value(i);
2230            let key = entry.child_value(0).get()?;
2231            let val = entry.child_value(1).get()?;
2232
2233            map.insert(key, val);
2234        }
2235
2236        Some(map)
2237    }
2238}
2239
2240impl<K, V> FromVariant for BTreeMap<K, V>
2241where
2242    K: FromVariant + Eq + Ord,
2243    V: FromVariant,
2244{
2245    fn from_variant(variant: &Variant) -> Option<Self> {
2246        if !variant.is_container() {
2247            return None;
2248        }
2249
2250        let mut map = BTreeMap::default();
2251
2252        for i in 0..variant.n_children() {
2253            let entry = variant.child_value(i);
2254            let key = entry.child_value(0).get()?;
2255            let val = entry.child_value(1).get()?;
2256
2257            map.insert(key, val);
2258        }
2259
2260        Some(map)
2261    }
2262}
2263
2264impl<K, V> ToVariant for HashMap<K, V>
2265where
2266    K: StaticVariantType + ToVariant + Eq + Hash,
2267    V: StaticVariantType + ToVariant,
2268{
2269    fn to_variant(&self) -> Variant {
2270        unsafe {
2271            if self.is_empty() {
2272                return from_glib_none(ffi::g_variant_new_array(
2273                    DictEntry::<K, V>::static_variant_type().to_glib_none().0,
2274                    ptr::null(),
2275                    0,
2276                ));
2277            }
2278
2279            let mut builder = mem::MaybeUninit::uninit();
2280            ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2281            let mut builder = builder.assume_init();
2282            for (key, value) in self {
2283                let entry = DictEntry::new(key, value).to_variant();
2284                ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
2285            }
2286            from_glib_none(ffi::g_variant_builder_end(&mut builder))
2287        }
2288    }
2289}
2290
2291impl<K, V> From<HashMap<K, V>> for Variant
2292where
2293    K: StaticVariantType + Into<Variant> + Eq + Hash,
2294    V: StaticVariantType + Into<Variant>,
2295{
2296    fn from(m: HashMap<K, V>) -> Self {
2297        unsafe {
2298            if m.is_empty() {
2299                return from_glib_none(ffi::g_variant_new_array(
2300                    DictEntry::<K, V>::static_variant_type().to_glib_none().0,
2301                    ptr::null(),
2302                    0,
2303                ));
2304            }
2305
2306            let mut builder = mem::MaybeUninit::uninit();
2307            ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2308            let mut builder = builder.assume_init();
2309            for (key, value) in m {
2310                let entry = Variant::from(DictEntry::new(key, value));
2311                ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
2312            }
2313            from_glib_none(ffi::g_variant_builder_end(&mut builder))
2314        }
2315    }
2316}
2317
2318impl<K, V> ToVariant for BTreeMap<K, V>
2319where
2320    K: StaticVariantType + ToVariant + Eq + Hash,
2321    V: StaticVariantType + ToVariant,
2322{
2323    fn to_variant(&self) -> Variant {
2324        unsafe {
2325            if self.is_empty() {
2326                return from_glib_none(ffi::g_variant_new_array(
2327                    DictEntry::<K, V>::static_variant_type().to_glib_none().0,
2328                    ptr::null(),
2329                    0,
2330                ));
2331            }
2332
2333            let mut builder = mem::MaybeUninit::uninit();
2334            ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2335            let mut builder = builder.assume_init();
2336            for (key, value) in self {
2337                let entry = DictEntry::new(key, value).to_variant();
2338                ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
2339            }
2340            from_glib_none(ffi::g_variant_builder_end(&mut builder))
2341        }
2342    }
2343}
2344
2345impl<K, V> From<BTreeMap<K, V>> for Variant
2346where
2347    K: StaticVariantType + Into<Variant> + Eq + Hash,
2348    V: StaticVariantType + Into<Variant>,
2349{
2350    fn from(m: BTreeMap<K, V>) -> Self {
2351        unsafe {
2352            if m.is_empty() {
2353                return from_glib_none(ffi::g_variant_new_array(
2354                    DictEntry::<K, V>::static_variant_type().to_glib_none().0,
2355                    ptr::null(),
2356                    0,
2357                ));
2358            }
2359
2360            let mut builder = mem::MaybeUninit::uninit();
2361            ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::ARRAY.to_glib_none().0);
2362            let mut builder = builder.assume_init();
2363            for (key, value) in m {
2364                let entry = Variant::from(DictEntry::new(key, value));
2365                ffi::g_variant_builder_add_value(&mut builder, entry.to_glib_none().0);
2366            }
2367            from_glib_none(ffi::g_variant_builder_end(&mut builder))
2368        }
2369    }
2370}
2371
2372/// A Dictionary entry.
2373///
2374/// While GVariant format allows a dictionary entry to be an independent type, typically you'll need
2375/// to use this in a dictionary, which is simply an array of dictionary entries. The following code
2376/// creates a dictionary:
2377///
2378/// ```
2379///# use glib::prelude::*; // or `use gtk::prelude::*;`
2380/// use glib::variant::{Variant, FromVariant, DictEntry};
2381///
2382/// let entries = [
2383///     DictEntry::new("uuid", 1000u32),
2384///     DictEntry::new("guid", 1001u32),
2385/// ];
2386/// let dict = entries.into_iter().collect::<Variant>();
2387/// assert_eq!(dict.n_children(), 2);
2388/// assert_eq!(dict.type_().as_str(), "a{su}");
2389/// ```
2390#[derive(Debug, Clone)]
2391pub struct DictEntry<K, V> {
2392    key: K,
2393    value: V,
2394}
2395
2396impl<K, V> DictEntry<K, V>
2397where
2398    K: StaticVariantType,
2399    V: StaticVariantType,
2400{
2401    pub fn new(key: K, value: V) -> Self {
2402        Self { key, value }
2403    }
2404
2405    pub fn key(&self) -> &K {
2406        &self.key
2407    }
2408
2409    pub fn value(&self) -> &V {
2410        &self.value
2411    }
2412}
2413
2414impl<K, V> FromVariant for DictEntry<K, V>
2415where
2416    K: FromVariant,
2417    V: FromVariant,
2418{
2419    fn from_variant(variant: &Variant) -> Option<Self> {
2420        if !variant.type_().is_subtype_of(VariantTy::DICT_ENTRY) {
2421            return None;
2422        }
2423
2424        let key = variant.child_value(0).get()?;
2425        let value = variant.child_value(1).get()?;
2426
2427        Some(Self { key, value })
2428    }
2429}
2430
2431impl<K, V> ToVariant for DictEntry<K, V>
2432where
2433    K: StaticVariantType + ToVariant,
2434    V: StaticVariantType + ToVariant,
2435{
2436    fn to_variant(&self) -> Variant {
2437        Variant::from_dict_entry(&self.key.to_variant(), &self.value.to_variant())
2438    }
2439}
2440
2441impl<K, V> From<DictEntry<K, V>> for Variant
2442where
2443    K: StaticVariantType + Into<Variant>,
2444    V: StaticVariantType + Into<Variant>,
2445{
2446    fn from(e: DictEntry<K, V>) -> Self {
2447        Variant::from_dict_entry(&e.key.into(), &e.value.into())
2448    }
2449}
2450
2451impl ToVariant for Variant {
2452    fn to_variant(&self) -> Variant {
2453        Variant::from_variant(self)
2454    }
2455}
2456
2457impl FromVariant for Variant {
2458    fn from_variant(variant: &Variant) -> Option<Self> {
2459        variant.as_variant()
2460    }
2461}
2462
2463impl<K: StaticVariantType, V: StaticVariantType> StaticVariantType for DictEntry<K, V> {
2464    fn static_variant_type() -> Cow<'static, VariantTy> {
2465        Cow::Owned(VariantType::new_dict_entry(
2466            &K::static_variant_type(),
2467            &V::static_variant_type(),
2468        ))
2469    }
2470}
2471
2472fn static_variant_mapping<K, V>() -> Cow<'static, VariantTy>
2473where
2474    K: StaticVariantType,
2475    V: StaticVariantType,
2476{
2477    use std::fmt::Write;
2478
2479    let key_type = K::static_variant_type();
2480    let value_type = V::static_variant_type();
2481
2482    if key_type == VariantTy::STRING && value_type == VariantTy::VARIANT {
2483        return Cow::Borrowed(VariantTy::VARDICT);
2484    }
2485
2486    let mut builder = crate::GStringBuilder::default();
2487    write!(builder, "a{{{}{}}}", key_type.as_str(), value_type.as_str()).unwrap();
2488
2489    Cow::Owned(VariantType::from_string(builder.into_string()).unwrap())
2490}
2491
2492impl<K, V, H> StaticVariantType for HashMap<K, V, H>
2493where
2494    K: StaticVariantType,
2495    V: StaticVariantType,
2496    H: BuildHasher + Default,
2497{
2498    fn static_variant_type() -> Cow<'static, VariantTy> {
2499        static_variant_mapping::<K, V>()
2500    }
2501}
2502
2503impl<K, V> StaticVariantType for BTreeMap<K, V>
2504where
2505    K: StaticVariantType,
2506    V: StaticVariantType,
2507{
2508    fn static_variant_type() -> Cow<'static, VariantTy> {
2509        static_variant_mapping::<K, V>()
2510    }
2511}
2512
2513macro_rules! tuple_impls {
2514    ($($len:expr => ($($n:tt $name:ident)+))+) => {
2515        $(
2516            impl<$($name),+> StaticVariantType for ($($name,)+)
2517            where
2518                $($name: StaticVariantType,)+
2519            {
2520                fn static_variant_type() -> Cow<'static, VariantTy> {
2521                    Cow::Owned(VariantType::new_tuple(&[
2522                        $(
2523                            $name::static_variant_type(),
2524                        )+
2525                    ]))
2526                }
2527            }
2528
2529            impl<$($name),+> FromVariant for ($($name,)+)
2530            where
2531                $($name: FromVariant,)+
2532            {
2533                fn from_variant(variant: &Variant) -> Option<Self> {
2534                    if !variant.type_().is_subtype_of(VariantTy::TUPLE) {
2535                        return None;
2536                    }
2537
2538                    Some((
2539                        $(
2540                            match variant.try_child_get::<$name>($n) {
2541                                Ok(Some(field)) => field,
2542                                _ => return None,
2543                            },
2544                        )+
2545                    ))
2546                }
2547            }
2548
2549            impl<$($name),+> ToVariant for ($($name,)+)
2550            where
2551                $($name: ToVariant,)+
2552            {
2553                fn to_variant(&self) -> Variant {
2554                    unsafe {
2555                        let mut builder = mem::MaybeUninit::uninit();
2556                        ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
2557                        let mut builder = builder.assume_init();
2558
2559                        $(
2560                            let field = self.$n.to_variant();
2561                            ffi::g_variant_builder_add_value(&mut builder, field.to_glib_none().0);
2562                        )+
2563
2564                        from_glib_none(ffi::g_variant_builder_end(&mut builder))
2565                    }
2566                }
2567            }
2568
2569            impl<$($name),+> From<($($name,)+)> for Variant
2570            where
2571                $($name: Into<Variant>,)+
2572            {
2573                fn from(t: ($($name,)+)) -> Self {
2574                    unsafe {
2575                        let mut builder = mem::MaybeUninit::uninit();
2576                        ffi::g_variant_builder_init(builder.as_mut_ptr(), VariantTy::TUPLE.to_glib_none().0);
2577                        let mut builder = builder.assume_init();
2578
2579                        $(
2580                            let field = t.$n.into();
2581                            ffi::g_variant_builder_add_value(&mut builder, field.to_glib_none().0);
2582                        )+
2583
2584                        from_glib_none(ffi::g_variant_builder_end(&mut builder))
2585                    }
2586                }
2587            }
2588        )+
2589    }
2590}
2591
2592tuple_impls! {
2593    1 => (0 T0)
2594    2 => (0 T0 1 T1)
2595    3 => (0 T0 1 T1 2 T2)
2596    4 => (0 T0 1 T1 2 T2 3 T3)
2597    5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
2598    6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
2599    7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
2600    8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
2601    9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
2602    10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
2603    11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
2604    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)
2605    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)
2606    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)
2607    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)
2608    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)
2609}
2610
2611impl<T: Into<Variant> + StaticVariantType> FromIterator<T> for Variant {
2612    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
2613        Variant::array_from_iter::<T>(iter.into_iter().map(|v| v.into()))
2614    }
2615}
2616
2617/// Trait for fixed size variant types.
2618pub unsafe trait FixedSizeVariantType: StaticVariantType + Sized + Copy {}
2619unsafe impl FixedSizeVariantType for u8 {}
2620unsafe impl FixedSizeVariantType for i16 {}
2621unsafe impl FixedSizeVariantType for u16 {}
2622unsafe impl FixedSizeVariantType for i32 {}
2623unsafe impl FixedSizeVariantType for u32 {}
2624unsafe impl FixedSizeVariantType for i64 {}
2625unsafe impl FixedSizeVariantType for u64 {}
2626unsafe impl FixedSizeVariantType for f64 {}
2627unsafe impl FixedSizeVariantType for bool {}
2628
2629/// Wrapper type for fixed size type arrays.
2630///
2631/// Converting this from/to a `Variant` is generally more efficient than working on the type
2632/// directly. This is especially important when deriving `Variant` trait implementations on custom
2633/// types.
2634///
2635/// This wrapper type can hold for example `Vec<u8>`, `Box<[u8]>` and similar types.
2636#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2637pub struct FixedSizeVariantArray<A, T>(A, std::marker::PhantomData<T>)
2638where
2639    A: AsRef<[T]>,
2640    T: FixedSizeVariantType;
2641
2642impl<A: AsRef<[T]>, T: FixedSizeVariantType> From<A> for FixedSizeVariantArray<A, T> {
2643    fn from(array: A) -> Self {
2644        FixedSizeVariantArray(array, std::marker::PhantomData)
2645    }
2646}
2647
2648impl<A: AsRef<[T]>, T: FixedSizeVariantType> FixedSizeVariantArray<A, T> {
2649    pub fn into_inner(self) -> A {
2650        self.0
2651    }
2652}
2653
2654impl<A: AsRef<[T]>, T: FixedSizeVariantType> std::ops::Deref for FixedSizeVariantArray<A, T> {
2655    type Target = A;
2656
2657    #[inline]
2658    fn deref(&self) -> &Self::Target {
2659        &self.0
2660    }
2661}
2662
2663impl<A: AsRef<[T]>, T: FixedSizeVariantType> std::ops::DerefMut for FixedSizeVariantArray<A, T> {
2664    #[inline]
2665    fn deref_mut(&mut self) -> &mut Self::Target {
2666        &mut self.0
2667    }
2668}
2669
2670impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsRef<A> for FixedSizeVariantArray<A, T> {
2671    #[inline]
2672    fn as_ref(&self) -> &A {
2673        &self.0
2674    }
2675}
2676
2677impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsMut<A> for FixedSizeVariantArray<A, T> {
2678    #[inline]
2679    fn as_mut(&mut self) -> &mut A {
2680        &mut self.0
2681    }
2682}
2683
2684impl<A: AsRef<[T]>, T: FixedSizeVariantType> AsRef<[T]> for FixedSizeVariantArray<A, T> {
2685    #[inline]
2686    fn as_ref(&self) -> &[T] {
2687        self.0.as_ref()
2688    }
2689}
2690
2691impl<A: AsRef<[T]> + AsMut<[T]>, T: FixedSizeVariantType> AsMut<[T]>
2692    for FixedSizeVariantArray<A, T>
2693{
2694    #[inline]
2695    fn as_mut(&mut self) -> &mut [T] {
2696        self.0.as_mut()
2697    }
2698}
2699
2700impl<A: AsRef<[T]>, T: FixedSizeVariantType> StaticVariantType for FixedSizeVariantArray<A, T> {
2701    fn static_variant_type() -> Cow<'static, VariantTy> {
2702        <[T]>::static_variant_type()
2703    }
2704}
2705
2706impl<A: AsRef<[T]> + for<'a> From<&'a [T]>, T: FixedSizeVariantType> FromVariant
2707    for FixedSizeVariantArray<A, T>
2708{
2709    fn from_variant(variant: &Variant) -> Option<Self> {
2710        Some(FixedSizeVariantArray(
2711            A::from(variant.fixed_array::<T>().ok()?),
2712            std::marker::PhantomData,
2713        ))
2714    }
2715}
2716
2717impl<A: AsRef<[T]>, T: FixedSizeVariantType> ToVariant for FixedSizeVariantArray<A, T> {
2718    fn to_variant(&self) -> Variant {
2719        Variant::array_from_fixed_array(self.0.as_ref())
2720    }
2721}
2722
2723impl<A: AsRef<[T]> + 'static, T: FixedSizeVariantType> From<FixedSizeVariantArray<A, T>>
2724    for Variant
2725{
2726    #[doc(alias = "g_variant_new_from_data")]
2727    fn from(a: FixedSizeVariantArray<A, T>) -> Self {
2728        unsafe {
2729            let data = Box::new(a.0);
2730            let (data_ptr, len) = {
2731                let data = (*data).as_ref();
2732                (data.as_ptr(), mem::size_of_val(data))
2733            };
2734
2735            unsafe extern "C" fn free_data<A: AsRef<[T]>, T: FixedSizeVariantType>(
2736                ptr: ffi::gpointer,
2737            ) {
2738                unsafe {
2739                    let _ = Box::from_raw(ptr as *mut A);
2740                }
2741            }
2742
2743            from_glib_none(ffi::g_variant_new_from_data(
2744                T::static_variant_type().to_glib_none().0,
2745                data_ptr as ffi::gconstpointer,
2746                len,
2747                false.into_glib(),
2748                Some(free_data::<A, T>),
2749                Box::into_raw(data) as ffi::gpointer,
2750            ))
2751        }
2752    }
2753}
2754
2755/// A wrapper type around `Variant` handles.
2756#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2757pub struct Handle(pub i32);
2758
2759impl From<i32> for Handle {
2760    fn from(v: i32) -> Self {
2761        Handle(v)
2762    }
2763}
2764
2765impl From<Handle> for i32 {
2766    fn from(v: Handle) -> Self {
2767        v.0
2768    }
2769}
2770
2771impl StaticVariantType for Handle {
2772    fn static_variant_type() -> Cow<'static, VariantTy> {
2773        Cow::Borrowed(VariantTy::HANDLE)
2774    }
2775}
2776
2777impl ToVariant for Handle {
2778    fn to_variant(&self) -> Variant {
2779        unsafe { from_glib_none(ffi::g_variant_new_handle(self.0)) }
2780    }
2781}
2782
2783impl From<Handle> for Variant {
2784    #[inline]
2785    fn from(h: Handle) -> Self {
2786        h.to_variant()
2787    }
2788}
2789
2790impl FromVariant for Handle {
2791    fn from_variant(variant: &Variant) -> Option<Self> {
2792        unsafe {
2793            if variant.is::<Self>() {
2794                Some(Handle(ffi::g_variant_get_handle(variant.to_glib_none().0)))
2795            } else {
2796                None
2797            }
2798        }
2799    }
2800}
2801
2802/// A wrapper type around `Variant` object paths.
2803///
2804/// Values of these type are guaranteed to be valid object paths.
2805#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2806pub struct ObjectPath(String);
2807
2808impl ObjectPath {
2809    pub fn as_str(&self) -> &str {
2810        &self.0
2811    }
2812}
2813
2814impl Display for ObjectPath {
2815    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2816        self.0.fmt(f)
2817    }
2818}
2819
2820impl std::ops::Deref for ObjectPath {
2821    type Target = str;
2822
2823    #[inline]
2824    fn deref(&self) -> &Self::Target {
2825        &self.0
2826    }
2827}
2828
2829impl TryFrom<String> for ObjectPath {
2830    type Error = crate::BoolError;
2831
2832    fn try_from(v: String) -> Result<Self, Self::Error> {
2833        if !Variant::is_object_path(&v) {
2834            return Err(bool_error!("Invalid object path"));
2835        }
2836
2837        Ok(ObjectPath(v))
2838    }
2839}
2840
2841impl<'a> TryFrom<&'a str> for ObjectPath {
2842    type Error = crate::BoolError;
2843
2844    fn try_from(v: &'a str) -> Result<Self, Self::Error> {
2845        ObjectPath::try_from(String::from(v))
2846    }
2847}
2848
2849impl From<ObjectPath> for String {
2850    fn from(v: ObjectPath) -> Self {
2851        v.0
2852    }
2853}
2854
2855impl StaticVariantType for ObjectPath {
2856    fn static_variant_type() -> Cow<'static, VariantTy> {
2857        Cow::Borrowed(VariantTy::OBJECT_PATH)
2858    }
2859}
2860
2861impl ToVariant for ObjectPath {
2862    fn to_variant(&self) -> Variant {
2863        unsafe { from_glib_none(ffi::g_variant_new_object_path(self.0.to_glib_none().0)) }
2864    }
2865}
2866
2867impl From<ObjectPath> for Variant {
2868    #[inline]
2869    fn from(p: ObjectPath) -> Self {
2870        let mut s = p.0;
2871        s.push('\0');
2872        unsafe { Self::from_data_trusted::<ObjectPath, _>(s) }
2873    }
2874}
2875
2876impl FromVariant for ObjectPath {
2877    #[allow(unused_unsafe)]
2878    fn from_variant(variant: &Variant) -> Option<Self> {
2879        unsafe {
2880            if variant.is::<Self>() {
2881                Some(ObjectPath(String::from(variant.str().unwrap())))
2882            } else {
2883                None
2884            }
2885        }
2886    }
2887}
2888
2889/// A wrapper type around `Variant` signatures.
2890///
2891/// Values of these type are guaranteed to be valid signatures.
2892#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2893pub struct Signature(String);
2894
2895impl Signature {
2896    pub fn as_str(&self) -> &str {
2897        &self.0
2898    }
2899}
2900
2901impl std::ops::Deref for Signature {
2902    type Target = str;
2903
2904    #[inline]
2905    fn deref(&self) -> &Self::Target {
2906        &self.0
2907    }
2908}
2909
2910impl TryFrom<String> for Signature {
2911    type Error = crate::BoolError;
2912
2913    fn try_from(v: String) -> Result<Self, Self::Error> {
2914        if !Variant::is_signature(&v) {
2915            return Err(bool_error!("Invalid signature"));
2916        }
2917
2918        Ok(Signature(v))
2919    }
2920}
2921
2922impl<'a> TryFrom<&'a str> for Signature {
2923    type Error = crate::BoolError;
2924
2925    fn try_from(v: &'a str) -> Result<Self, Self::Error> {
2926        Signature::try_from(String::from(v))
2927    }
2928}
2929
2930impl From<Signature> for String {
2931    fn from(v: Signature) -> Self {
2932        v.0
2933    }
2934}
2935
2936impl StaticVariantType for Signature {
2937    fn static_variant_type() -> Cow<'static, VariantTy> {
2938        Cow::Borrowed(VariantTy::SIGNATURE)
2939    }
2940}
2941
2942impl ToVariant for Signature {
2943    fn to_variant(&self) -> Variant {
2944        unsafe { from_glib_none(ffi::g_variant_new_signature(self.0.to_glib_none().0)) }
2945    }
2946}
2947
2948impl From<Signature> for Variant {
2949    #[inline]
2950    fn from(s: Signature) -> Self {
2951        let mut s = s.0;
2952        s.push('\0');
2953        unsafe { Self::from_data_trusted::<Signature, _>(s) }
2954    }
2955}
2956
2957impl FromVariant for Signature {
2958    #[allow(unused_unsafe)]
2959    fn from_variant(variant: &Variant) -> Option<Self> {
2960        unsafe {
2961            if variant.is::<Self>() {
2962                Some(Signature(String::from(variant.str().unwrap())))
2963            } else {
2964                None
2965            }
2966        }
2967    }
2968}
2969
2970#[cfg(test)]
2971mod tests {
2972    use std::collections::{HashMap, HashSet};
2973
2974    use super::*;
2975
2976    macro_rules! unsigned {
2977        ($name:ident, $ty:ident) => {
2978            #[test]
2979            fn $name() {
2980                let mut n = $ty::MAX;
2981                while n > 0 {
2982                    let v = n.to_variant();
2983                    assert_eq!(v.get(), Some(n));
2984                    n /= 2;
2985                }
2986            }
2987        };
2988    }
2989
2990    macro_rules! signed {
2991        ($name:ident, $ty:ident) => {
2992            #[test]
2993            fn $name() {
2994                let mut n = $ty::MAX;
2995                while n > 0 {
2996                    let v = n.to_variant();
2997                    assert_eq!(v.get(), Some(n));
2998                    let v = (-n).to_variant();
2999                    assert_eq!(v.get(), Some(-n));
3000                    n /= 2;
3001                }
3002            }
3003        };
3004    }
3005
3006    unsigned!(test_u8, u8);
3007    unsigned!(test_u16, u16);
3008    unsigned!(test_u32, u32);
3009    unsigned!(test_u64, u64);
3010    signed!(test_i16, i16);
3011    signed!(test_i32, i32);
3012    signed!(test_i64, i64);
3013
3014    #[test]
3015    fn test_str() {
3016        let s = "this is a test";
3017        let v = s.to_variant();
3018        assert_eq!(v.str(), Some(s));
3019        assert_eq!(42u32.to_variant().str(), None);
3020    }
3021
3022    #[test]
3023    fn test_fixed_array() {
3024        let b = b"this is a test";
3025        let v = Variant::array_from_fixed_array(&b[..]);
3026        assert_eq!(v.type_().as_str(), "ay");
3027        assert_eq!(v.fixed_array::<u8>().unwrap(), b);
3028        assert!(42u32.to_variant().fixed_array::<u8>().is_err());
3029
3030        let b = [1u32, 10u32, 100u32];
3031        let v = Variant::array_from_fixed_array(&b);
3032        assert_eq!(v.type_().as_str(), "au");
3033        assert_eq!(v.fixed_array::<u32>().unwrap(), b);
3034        assert!(v.fixed_array::<u8>().is_err());
3035
3036        let b = [true, false, true];
3037        let v = Variant::array_from_fixed_array(&b);
3038        assert_eq!(v.type_().as_str(), "ab");
3039        assert_eq!(v.fixed_array::<bool>().unwrap(), b);
3040        assert!(v.fixed_array::<u8>().is_err());
3041
3042        let b = [1.0f64, 2.0f64, 3.0f64];
3043        let v = Variant::array_from_fixed_array(&b);
3044        assert_eq!(v.type_().as_str(), "ad");
3045        #[allow(clippy::float_cmp)]
3046        {
3047            assert_eq!(v.fixed_array::<f64>().unwrap(), b);
3048        }
3049        assert!(v.fixed_array::<u64>().is_err());
3050    }
3051
3052    #[test]
3053    fn test_fixed_variant_array() {
3054        let b = FixedSizeVariantArray::from(&b"this is a test"[..]);
3055        let v = b.to_variant();
3056        assert_eq!(v.type_().as_str(), "ay");
3057        assert_eq!(
3058            &*v.get::<FixedSizeVariantArray<Vec<u8>, u8>>().unwrap(),
3059            &*b
3060        );
3061
3062        let b = FixedSizeVariantArray::from(vec![1i32, 2, 3]);
3063        let v = b.to_variant();
3064        assert_eq!(v.type_().as_str(), "ai");
3065        assert_eq!(v.get::<FixedSizeVariantArray<Vec<i32>, i32>>().unwrap(), b);
3066    }
3067
3068    #[test]
3069    fn test_string() {
3070        let s = String::from("this is a test");
3071        let v = s.to_variant();
3072        assert_eq!(v.get(), Some(s));
3073        assert_eq!(v.normal_form(), v);
3074    }
3075
3076    #[test]
3077    fn test_eq() {
3078        let v1 = "this is a test".to_variant();
3079        let v2 = "this is a test".to_variant();
3080        let v3 = "test".to_variant();
3081        assert_eq!(v1, v2);
3082        assert_ne!(v1, v3);
3083    }
3084
3085    #[test]
3086    fn test_hash() {
3087        let v1 = "this is a test".to_variant();
3088        let v2 = "this is a test".to_variant();
3089        let v3 = "test".to_variant();
3090        let mut set = HashSet::new();
3091        set.insert(v1);
3092        assert!(set.contains(&v2));
3093        assert!(!set.contains(&v3));
3094
3095        assert_eq!(
3096            <HashMap<&str, (&str, u8, u32)>>::static_variant_type().as_str(),
3097            "a{s(syu)}"
3098        );
3099    }
3100
3101    #[test]
3102    fn test_array() {
3103        assert_eq!(<Vec<&str>>::static_variant_type().as_str(), "as");
3104        assert_eq!(
3105            <Vec<(&str, u8, u32)>>::static_variant_type().as_str(),
3106            "a(syu)"
3107        );
3108        let a = ["foo", "bar", "baz"].to_variant();
3109        assert_eq!(a.normal_form(), a);
3110        assert_eq!(a.array_iter_str().unwrap().len(), 3);
3111        let o = 0u32.to_variant();
3112        assert!(o.array_iter_str().is_err());
3113    }
3114
3115    #[test]
3116    fn test_array_from_iter() {
3117        let a = Variant::array_from_iter::<String>(
3118            ["foo", "bar", "baz"].into_iter().map(|s| s.to_variant()),
3119        );
3120        assert_eq!(a.type_().as_str(), "as");
3121        assert_eq!(a.n_children(), 3);
3122
3123        assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
3124        assert_eq!(a.try_child_get::<String>(1), Ok(Some(String::from("bar"))));
3125        assert_eq!(a.try_child_get::<String>(2), Ok(Some(String::from("baz"))));
3126    }
3127
3128    #[test]
3129    fn test_array_collect() {
3130        let a = ["foo", "bar", "baz"].into_iter().collect::<Variant>();
3131        assert_eq!(a.type_().as_str(), "as");
3132        assert_eq!(a.n_children(), 3);
3133
3134        assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
3135        assert_eq!(a.try_child_get::<String>(1), Ok(Some(String::from("bar"))));
3136        assert_eq!(a.try_child_get::<String>(2), Ok(Some(String::from("baz"))));
3137    }
3138
3139    #[test]
3140    fn test_tuple() {
3141        assert_eq!(<(&str, u32)>::static_variant_type().as_str(), "(su)");
3142        assert_eq!(<(&str, u8, u32)>::static_variant_type().as_str(), "(syu)");
3143        let a = ("test", 1u8, 2u32).to_variant();
3144        assert_eq!(a.normal_form(), a);
3145        assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("test"))));
3146        assert_eq!(a.try_child_get::<u8>(1), Ok(Some(1u8)));
3147        assert_eq!(a.try_child_get::<u32>(2), Ok(Some(2u32)));
3148        assert_eq!(
3149            a.try_get::<(String, u8, u32)>(),
3150            Ok((String::from("test"), 1u8, 2u32))
3151        );
3152    }
3153
3154    #[test]
3155    fn test_tuple_from_iter() {
3156        let a = Variant::tuple_from_iter(["foo".to_variant(), 1u8.to_variant(), 2i32.to_variant()]);
3157        assert_eq!(a.type_().as_str(), "(syi)");
3158        assert_eq!(a.n_children(), 3);
3159
3160        assert_eq!(a.try_child_get::<String>(0), Ok(Some(String::from("foo"))));
3161        assert_eq!(a.try_child_get::<u8>(1), Ok(Some(1u8)));
3162        assert_eq!(a.try_child_get::<i32>(2), Ok(Some(2i32)));
3163    }
3164
3165    #[test]
3166    fn test_empty() {
3167        assert_eq!(<()>::static_variant_type().as_str(), "()");
3168        let a = ().to_variant();
3169        assert_eq!(a.type_().as_str(), "()");
3170        assert_eq!(a.get::<()>(), Some(()));
3171    }
3172
3173    #[test]
3174    fn test_maybe() {
3175        assert!(<Option<()>>::static_variant_type().is_maybe());
3176        let m1 = Some(()).to_variant();
3177        assert_eq!(m1.type_().as_str(), "m()");
3178
3179        assert_eq!(m1.get::<Option<()>>(), Some(Some(())));
3180        assert!(m1.as_maybe().is_some());
3181
3182        let m2 = None::<()>.to_variant();
3183        assert!(m2.as_maybe().is_none());
3184    }
3185
3186    #[test]
3187    fn test_btreemap() {
3188        assert_eq!(
3189            <BTreeMap<String, u32>>::static_variant_type().as_str(),
3190            "a{su}"
3191        );
3192        // Validate that BTreeMap adds entries to dict in sorted order
3193        let mut m = BTreeMap::new();
3194        let total = 20;
3195        for n in 0..total {
3196            let k = format!("v{n:04}");
3197            m.insert(k, n as u32);
3198        }
3199        let v = m.to_variant();
3200        let n = v.n_children();
3201        assert_eq!(total, n);
3202        for n in 0..total {
3203            let child = v
3204                .try_child_get::<DictEntry<String, u32>>(n)
3205                .unwrap()
3206                .unwrap();
3207            assert_eq!(*child.value(), n as u32);
3208        }
3209
3210        assert_eq!(BTreeMap::from_variant(&v).unwrap(), m);
3211    }
3212
3213    #[test]
3214    fn test_get() -> Result<(), Box<dyn std::error::Error>> {
3215        let u = 42u32.to_variant();
3216        assert!(u.get::<i32>().is_none());
3217        assert_eq!(u.get::<u32>().unwrap(), 42);
3218        assert!(u.try_get::<i32>().is_err());
3219        // Test ? conversion
3220        assert_eq!(u.try_get::<u32>()?, 42);
3221        Ok(())
3222    }
3223
3224    #[test]
3225    fn test_byteswap() {
3226        let u = 42u32.to_variant();
3227        assert_eq!(u.byteswap().get::<u32>().unwrap(), 704643072u32);
3228        assert_eq!(u.byteswap().byteswap().get::<u32>().unwrap(), 42u32);
3229    }
3230
3231    #[test]
3232    fn test_try_child() {
3233        let a = ["foo"].to_variant();
3234        assert!(a.try_child_value(0).is_some());
3235        assert_eq!(a.try_child_get::<String>(0).unwrap().unwrap(), "foo");
3236        assert_eq!(a.child_get::<String>(0), "foo");
3237        assert!(a.try_child_get::<u32>(0).is_err());
3238        assert!(a.try_child_value(1).is_none());
3239        assert!(a.try_child_get::<String>(1).unwrap().is_none());
3240        let u = 42u32.to_variant();
3241        assert!(u.try_child_value(0).is_none());
3242        assert!(u.try_child_get::<String>(0).unwrap().is_none());
3243    }
3244
3245    #[test]
3246    fn test_serialize() {
3247        let a = ("test", 1u8, 2u32).to_variant();
3248
3249        let bytes = a.data_as_bytes();
3250        let data = a.data();
3251        let len = a.size();
3252        assert_eq!(bytes.len(), len);
3253        assert_eq!(data.len(), len);
3254
3255        let mut store_data = vec![0u8; len];
3256        assert_eq!(a.store(&mut store_data).unwrap(), len);
3257
3258        assert_eq!(&bytes, data);
3259        assert_eq!(&store_data, data);
3260
3261        let b = Variant::from_data::<(String, u8, u32), _>(store_data);
3262        assert_eq!(a, b);
3263
3264        let c = Variant::from_bytes::<(String, u8, u32)>(&bytes);
3265        assert_eq!(a, c);
3266    }
3267
3268    #[test]
3269    fn test_print_parse() {
3270        let a = ("test", 1u8, 2u32).to_variant();
3271
3272        let a2 = Variant::parse(Some(a.type_()), &a.print(false)).unwrap();
3273        assert_eq!(a, a2);
3274
3275        let a3: Variant = a.to_string().parse().unwrap();
3276        assert_eq!(a, a3);
3277    }
3278
3279    #[cfg(any(unix, windows))]
3280    #[test]
3281    fn test_paths() {
3282        use std::path::PathBuf;
3283
3284        let path = PathBuf::from("foo");
3285        let v = path.to_variant();
3286        assert_eq!(PathBuf::from_variant(&v), Some(path));
3287    }
3288
3289    #[test]
3290    fn test_regression_from_variant_panics() {
3291        let variant = "text".to_variant();
3292        let hashmap: Option<HashMap<u64, u64>> = FromVariant::from_variant(&variant);
3293        assert!(hashmap.is_none());
3294
3295        let variant = HashMap::<u64, u64>::new().to_variant();
3296        let hashmap: Option<HashMap<u64, u64>> = FromVariant::from_variant(&variant);
3297        assert!(hashmap.is_some());
3298    }
3299}