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