Skip to main content

glib/
variant.rs

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