glib/
variant.rs

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