glib/
variant.rs

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