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