glib/
variant.rs

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